Is it safe to pass a vector as an array?

11,491

Solution 1

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.

Solution 2

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.

Solution 3

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.

Share:
11,491
uj2
Author by

uj2

Updated on June 15, 2022

Comments

  • uj2
    uj2 about 2 years

    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).

  • PeterK
    PeterK about 14 years
    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.
  • JAB
    JAB about 14 years
    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?
  • James McNellis
    James McNellis about 14 years
    @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.
  • JAB
    JAB about 14 years
    @James: Don't worry, it's just me forgetting C++'s casting rules.
  • Billy ONeal
    Billy ONeal about 14 years
    While this is true, cplusplus.com is not a definitive reference.
  • PeterK
    PeterK about 14 years
    @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 ;)
  • mtvec
    mtvec about 14 years
    @Billy ONeal: You're right, I edited my answer to give a better quote.
  • AshleysBrain
    AshleysBrain about 14 years
    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.
  • sellibitze
    sellibitze about 14 years
    @PeterK: In case you are trying to invoke a function void fun(Derived**); using pointers stored in a vector<Base*> 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.
  • mtvec
    mtvec about 14 years
    @AshleysBrain: Can you point to the section in the standard describing that v[0] when v.empty() is UB?
  • JonM
    JonM about 14 years
    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.
  • Rob Kennedy
    Rob Kennedy about 14 years
    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.