C++ STL 容器和指针有效性
考虑这段代码:
Uint counter = 0;
int* p1;
int* p2;
deque<int> dequeInstance;
vector<int> vectorInstance;
dequeInstance.push_back(3);
dequeInstance.push_back(7);
p1 = &dequeInstance.back();
dequeInstance.push_back(17);
p2 = &dequeInstance.back();
if(*p1 == !7)
++counter;
if(*p2 == !17)
++counter;
vectorInstance.push_back(3);
vectorInstance.push_back(7);
p1 = &vectorInstance.back();
vectorInstance.push_back(17);
p2 = &vectorInstance.back();
if(*p1 == !7)
++counter;
if(*p2 == !17)
++counter;
return counter;
我本来期望当我将第三个元素推到向量的后面时,指向第二个元素的指针将无效,因为我对 std::vector 的理解是它是一个直数组每次修改时都会被擦除并重新创建。然而,到此代码结束时,“计数器”等于零。
我在这里缺少什么?
Consider this piece of code:
Uint counter = 0;
int* p1;
int* p2;
deque<int> dequeInstance;
vector<int> vectorInstance;
dequeInstance.push_back(3);
dequeInstance.push_back(7);
p1 = &dequeInstance.back();
dequeInstance.push_back(17);
p2 = &dequeInstance.back();
if(*p1 == !7)
++counter;
if(*p2 == !17)
++counter;
vectorInstance.push_back(3);
vectorInstance.push_back(7);
p1 = &vectorInstance.back();
vectorInstance.push_back(17);
p2 = &vectorInstance.back();
if(*p1 == !7)
++counter;
if(*p2 == !17)
++counter;
return counter;
I would have expected that when I pushed the third element to the back of the vector, the pointer to the second element would have been invalidated, as my understanding of std::vector is that its a straight array which is wiped and recreated every time its modified. By the end of this code however 'counter' is equal to zero.
What am I missing here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
希望出于性能考虑,
std::vector
不会“每次修改时都会被擦除并重新创建”。向量的
容量
可能会超过其大小
,这意味着它可以分配比实际使用更多的内存。当您push_back
时,仅当新大小大于旧容量时才会发生重新分配,并且在这种情况下,迭代器将失效。在您的情况下,您应该在
std::vector
实例化之后立即检查capacity
的值。您将看到它毫无疑问大于 3,因此,您的任何push_back
调用都不会触发重新分配,并且所有迭代器仍然有效。另请注意,
std::vector
提供了一个reserve
成员函数,允许您控制向量容量。当您知道需要插入多少元素以避免不可告人的重新分配时,这非常有用。Hopefully for performance,
std::vector
is not 'wiped and recreated every time it's modified'.A vector has a
capacity
which may exceed itssize
, which means that it can allocate more memory than truly used. When youpush_back
, a reallocation will only occur if the new size is greater than the old capacity, and in this case, iterators are invalidated.In your case, you should check the value of
capacity
right after thestd::vector
instantiation. You will see that it's without any doubt greater than 3, thus, none of yourpush_back
calls trigger a reallocation and all iterators remain valid.Also note that
std::vector
provides areserve
member function which allow you to control the vector capacity. This is really useful when you know how many elements are expected to be inserted in order to avoid ulterior reallocation.好吧,你有一些问题。首先,!n = 0,除非n = 0,然后它等于1。因此计数器永远不会增加。
其次,当您push_back一个新元素时,向量不一定会破坏内容。向量有 2 个“大小”。 1 是向量中的元素数量,2 是分配的内存量。仅当分配的内存量用完时,向量才会被重新分配和复制。
此外,删除内存区域后,内存不一定会被清除,并且可能仍然指向有效数据。
您没有使用迭代器,因此它们不会失效。您正在使用指针,它们只是指向内存区域。仅仅因为未分配内存并不意味着指针无效。这是 C/C++ 给您带来的主要危险之一。确保你不要做这样的事情,因为你正在调用“未定义的行为”,它可以做任何事情,从“不会引起任何问题并且看似工作”到“可怕地崩溃并以危险的方式关闭你的操作系统”。
Ok you have a few problems. Firstly, !n = 0 unless n = 0 and then it equals 1. Therefore counter never gets incremented.
Secondly a vector does not necessarily destroy the contents when you push_back a new element. A vector has 2 "sizes". 1 is the number of elements in the vector and 2 is the amount of memory allocated. The vector only gets reallocated and copied when the amount of memory allocated runs out.
Furthermore after you have deleted an area of memory the memory is not necessarily cleared and may still point at valid data.
You aren't using iterators so they don't get invalidated. You are using pointers and they are simply pointing at an area of memory. Just because that memory isn't allocated does not mean that the pointer is invalid. This is one of the major dangers that C/C++ can leave you with. Make sure you don't do things like this as you are invoking "undefined behaviour" which can do anything from "not cause any problems and seemingly work" through to "crash horrifically and bring down your operating system in a dangerous way".