Is it safe to compare with the std :: vector pointer to check for equality?

at a time, I created a pointer point to std::vector , then I performed some push_back , reserve , resize operation for this vector, after such operations it is safe to compare the pointer with the address of this vector to check if the pointer points to this vector, because there may be some reallocation of memory.

eg

 std::vector<int> vec; vector<int>* pVec = &vec; vec.reserve(10000); assert(pVec == &vec); vec = anotherVec; assert(pVec == &vec); 

what's more, is it safe to compare a pointer to the first value of a vector? eg:

 std::vector<int> vec(1,0); int* p = &vec[0]; // some operation here assert(p == &vec[0]); 

As I myself experienced, it seems that the first situation is safe and the second is not, but I can’t be sure.

+5
source share
5 answers
 std::vector<int> vec; vector<int>* pVec = &vec; vec.reserve(10000); assert(pVec == &vec); 

is safe.


 std::vector<int> vec(1,0); int* p = &vec[0]; // some operation here assert(p == &vec[0]); 

It is not safe.


The first block is safe, since the vec address will not change even when its contents change.

The second block is not safe, since the address vec[0] may change; for example, when vec resizes by itself; for example, when you click on items.

+7
source

it seems that the first situation is safe and the second is not

It is right. In the first “situation”, the vec object itself remains where it is in memory, regardless of the reserve call, which can move managed items to another area of ​​dynamic memory. This is because elements can be moved so that pointers can not compare the same in the second scenario.

+2
source

The second situation is safe until the move . If you know the size that you will need in advance and use reserve() before you get the pointer, it will be absolutely safe and you will save a bit of performance (one level less indirection).

However, any addition with push_back() , for example, may go beyond the allocated space and invalidate your pointer. std::vector optimized and will try to allocate more memory at the same position if possible (since it keeps copies of the data around), but you cannot be sure of that.

In this case, instead of accepting a pointer, you can take an iterator because the iterator on the vector behaves exactly like a pointer (and has no performance impact) with more type safety.

+2
source

vector<int>* pVec = &vec; works at the address of the std::vector<int> object, which is valid up to scope. vec = anotherVec; does not change the vec address because operator = of std::vector is called here. So both assert(pVec == &vec); successfully completed.

In the case of int* p = &vec[0]; it depends: see Iterator invalidation .

+1
source

The first case is really safe, since there is no danger of changing the address of a vector object. The second case is safe until redistribution occurs (redistribution can be traced using the member function std :: vector :: capacity), otherwise it is either undefined or the implementation is determined depending on the version of the language. See this answer for more information, as the same restrictions apply in this case.

+1
source

All Articles