Can address change when passing a c++ vector by pointer

If I have something like the code below, where I pass a vector pointer (e.g. it can be null), then in the called function I add items to the vector, is there danger that my vector pointer can become invalid? The same goes for passing by reference. Since vector is guaranteed to be contiguous in memory and will reallocate as needed is there danger that I could get a dangling pointer because the vector is relocated in memory? The code below is trivial but what if myVecFunc was adding a million values, or some large objects? I’ve seen library code that follows this pattern but it seems like you could run into trouble by doing this?
EDIT: Edited code to do *mVec->push_back(someNumber)

void myVecFunc(std::vector<double>* myVec)
{
     if (myVec != nullptr)
     {
        myVec->push_back(someNumber);
     }

}

int main(int argc, char* argv[])
{
   std::vector<double> myVec;
   myVecFunc(&myVec);
}

  • Definitely use a reference, not a pointer. And yes, it is safe to do so. It is actually common for a function with a std::vector<...>& parameter to call reserve() first thing in its body so that memory is reallocated to what it is going to need (it makes the function faster by guaranteeing only 1 reallocation occurs, that it occurs before new elements are inserted + it guarantees you can use iterators without risk, since it will not reallocate).

    – 




  • Please try to create a minimal reproducible example to show us.

    – 

  • 3

    myVec itself cannot and will not be realloacted by a call to a member function. it has its own internal pointer for managing the dynamically allocated array (which can refer to different addresses after a push_back)

    – 

  • Just write void myVecFunc(std::vector<double>& myVec) { myVec.push_back(someNumber); } And you will not even have to do nullptr validation.

    – 

  • 1

    Your edit is wrong. Either do (*myVec).push_back(...) (note the extra parenthesis around *myVec) or myVec->push_back(...)(No asterisk here). The latter form is almost always preferred. Or in your case, just pass by reference.

    – 

Frankly, you have two fundamental misunderstandings.

First, passing a pointer to a function: Function arguments are passed by value (unless you use references), pointers are no exception:

 void foo(int*);

 // usage
 int* x = nullptr;
 foo(x);
 assert( x == nullptr);

There is no way the assert could fail, because foo cannot modify x. In your example myVecFunc cannot modify the addressof myVec. The memory location of an object is tied to its identity. During lifetime it doesnt change. If you copy a vector to a different location, you get a copy.


Next std::vector. A vector internally stores a pointer to dynamically allocated memory used for the elements. The memory is properly managed by the vector. For example, you can copy a vector and it will copy the elements. You can pass a vector by pointer or by reference, no problem at all.

What can happen on a reallcoation that the pointer that the vector stores internally gets a different value. Hence this code should not be written like this:

std::vector<int> foo(2); // vector of size 2
int* ptr = foo.data();   // pointer to the internal array
foo.push_back(42);       // iterators and pointers are invalidated
std::cout << *ptr;       // DO NOT DERFERENCE THE INVALID POINTER !

In summary: There is nothing wrong in the code you show. However, you should only pass arguments by pointer when nullptr is a valid input. Otherwise use a reference.

Leave a Comment