简体   繁体   中英

Is it safe to compare to pointer of std::vector to check equality?

at a time, I created a pointer point to a std::vector , then I did some push_back , reserve , resize operation to that vector, after such operations, is it safe to compare the pointer to the address of that vector to check whether the pointer point to that vector, because there might be some re-allocation of memory.

for example

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

what is more, is it safe to compare a pointer to the first value of vector? for example:

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

As I tested by myself, it seems that the first situation is safe, while the second is not, but I can't be sure.

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]);

is not safe.


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

The second block is not safe since the address of vec[0] may change; for example when the vec resizes itself — eg, when you push_back elements to it.

it seems that the first situation is safe, while the second is not

That's right. In the first "situation", the vec object itself stays wherever it is in memory regardless of the reserve call, which might move the managed elements to another area of dynamic memory. It's because elements can be moved that the pointers may not compare equal in the second scenario.

The second situation is safe as long as no relocation takes place . If you know the size you will need in advance and use reserve() before you get the pointer it is perfectly safe and you save a little bit of performance (one less level of indirection).

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

For that matter, instead of taking a pointer you could take an iterator because an iterator on a vector behaves exactly like a pointer (and has no performance impact) with more type safety.

vector<int>* pVec = &vec; operates on the address of the std::vector<int> object which is valid till scope. vec = anotherVec; does not change the address of the vec because of here the operator = of std::vector is called. So, both assert(pVec == &vec); is successfully passed through.

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

The first case is indeed safe as there is no danger of the vector object's address changing. The second case is safe as long as no reallocation happens (reallocations can be traced using the std::vector::capacity member function), otherwise it's either undefined or implementation-defined depending on the version of the language. For more information consult this answer. since the same restrictions apply in that case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM