21

Say I have a function:

void someFunc(int *x,int count);

which is out of my control, so I can't write it to accept iterators.

Is it safe to call it like so (regardless of the specific STL implementation):

vector<int> v;
/* ... */
someFunc(&v[0],v.size());

Obviously, one counter example is vector<bool>. How about any other type? (assuming I haven't specialized vector in any way).

uj2
  • 2,255
  • 2
  • 21
  • 32
  • 2
    Effectively a duplicate of [Are std::vector elements guaranteed to be contiguous?](http://stackoverflow.com/questions/849168/are-stdvector-elements-guaranteed-to-be-contiguous) – James McNellis Jun 22 '10 at 13:20
  • 1
    +1 Interesting question. I have to admit that I am somewhat supprised that it is safe but it is useful information to have. – Robben_Ford_Fan_boy Jun 22 '10 at 13:27
  • @Job: `bool`s are one byte rather than the multibyte size of most `int` types? Which could be potentially be important depending on what `someFunc` actually does. – JAB Jun 22 '10 at 13:27

3 Answers3

33

From section 23.2.4, point 1 of the standard:

[...] The elements of a vector are stored contiguously, meaning that if v is a vector where T is some type other than bool, then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size().

So yes, it is safe.

Note: If v is empty v[0] is undefined behavior so you should only do this if v is not empty.

mtvec
  • 17,846
  • 5
  • 52
  • 83
  • 2
    While this is true, cplusplus.com is not a definitive reference. – Billy ONeal Jun 22 '10 at 13:30
  • @Billy ONeal: You're right, I edited my answer to give a better quote. – mtvec Jun 22 '10 at 13:38
  • 3
    It's not safe if the vector is empty, since `v[0]` or `v.front()` are undefined behavior that way. Since this is the top-voted and chosen answer, it would be good to include that. Also, if the function stores the pointer long-term and the vector is freed or reallocates, the pointer becomes invalid. – AshleysBrain Jun 22 '10 at 13:56
  • @AshleysBrain: Can you point to the section in the standard describing that `v[0]` when `v.empty()` is UB? – mtvec Jun 22 '10 at 14:43
  • Accessing `v[0]` is undefined behavior, but is it UB to take the address: `&v[0]`? If you pass in a size of 0 to any well written function, it won't touch the array. – JonM Jun 22 '10 at 15:31
  • 4
    Yes, @Jon, it's still undefined. You're calling the `vector::operator[]` function on a vector that has no elements. That *in and of itself* is undefined. At the point you're taking the address of the result and deciding whether or not to dereference that pointer, you're *already* in undefined-behavior territory. Nothing you do or don't do afterward can bring you back. – Rob Kennedy Jun 22 '10 at 16:42
11

As others has suggested it is safe.

But I would like to have a small reservation. If this function accept an array and stores it for later use you might have a problem. This is because std::vector might freely deallocate its memory if it needs it to change size. So if this function just uses the array (makes a copy or whatever) or you never alter it, it is safe.

I just want to point that out, just because the vectors elements are stored contiguous it isn't automatically safe to pass around. Ownership is still an issue.

daramarak
  • 6,115
  • 1
  • 31
  • 50
9

Yes. Assuming v.size() > 0, this is safe (If the vector is empty, then v[0] results in undefined behavior).

The elements of a std::vector container are stored contiguously, just like in an ordinary array.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • In this case, yes. Would it be safe even with a vector with pointers to a base class? (so at runtime, pointers to derived classes could be passed). Assuming that someFunc() will dereference those, of course. – PeterK Jun 22 '10 at 13:22
  • The value of a pointer is just an integer, so technically it would work, but you'd probably still get a warning or error for passing an array of pointers to classes rather than an array of integers unless you messed with casting. Or does C++ allow passing pointers as integers without explicit casting? – JAB Jun 22 '10 at 13:25
  • 1
    @PeterK: Yes; why do you think it wouldn't it work with pointer elements? @JAB: I really don't know what you are trying to say. – James McNellis Jun 22 '10 at 13:26
  • @James: Don't worry, it's just me forgetting C++'s casting rules. – JAB Jun 22 '10 at 13:28
  • @James McNellis: Sorry, i was just confused. It would of course work. (What i had in mind was that derived classes may be bigger than their base classes (when it comes to memory)). This of course does not affect pointers ;) – PeterK Jun 22 '10 at 13:32
  • @PeterK: In case you are trying to invoke a function `void fun(Derived**);` using pointers stored in a `vector vec;` the answer is no. `&vec[0]` is of type `Base**` and this is not the same as `Derived**` or even convertible to it. You could `reinterpret_cast` it, but it's technically undefined behaviour and it will blow up in your face if you toy with multiple inheritence where a conversion from `Derived*` to `Base*` may require a pointer adjustment. – sellibitze Jun 22 '10 at 14:15