C++ 通过原始指针访问的向量元素意外更改了值

C++ 通过原始指针访问的向量元素意外更改了值,c++,pointers,stdvector,C++,Pointers,Stdvector,以下程序的意外行为(尽可能简短): 为什么通过vec.data\u0].my\u i访问vec.data\u0].cached.owner\ui时,会以一种无意义、依赖于编译器的方式覆盖vec.data\u0].my\u i的值 当我将CachingVector::resize()的两行实现合并到构造函数CachingVector()中时,I=97保持未损坏状态。您正在向量中存储指向临时对象的指针(特别是在CachedPayload::owner\uz>中)。这就是问题的原因。一旦临时文件被销毁

以下程序的意外行为(尽可能简短):

为什么通过
vec.data\u0].my\u i
访问
vec.data\u0].cached.owner\ui
时,会以一种无意义、依赖于编译器的方式覆盖
vec.data\u0].my\u i
的值


当我将
CachingVector::resize()
的两行实现合并到构造函数
CachingVector()
中时,
I=97
保持未损坏状态。

您正在向量中存储指向临时对象的指针(特别是在
CachedPayload::owner\uz>中)。这就是问题的原因。一旦临时文件被销毁,你就会有一个悬空的指针

我将此添加到您的代码中

~Entry() { std::cout << "destroyed " << this << std::endl; }
新的输出是

destroyed 00000000001AF588
RSZ: this=00000000001AF588, i=97
GET: this=00000000001AF588, i=-858993460
正如您所看到的,您正在访问一个已被销毁的对象,这当然是未定义的行为

要解决这个问题,我认为您只需要为
条目
定义一个复制构造函数和赋值运算符,以确保
缓存的.owner总是具有正确的值

Entry(const Entry& rhs) : cached(this), my_i(rhs.my_i) {}
Entry& operator=(const Entry& rhs) { my_i = rhs.my_i; return *this; }

指向向量底层数组的原始指针可能会因任何变异操作而无效,如
调整大小
推回
,等等。这是一种不安全的设计,原因正是您刚才演示的谢谢。听起来很贴切。我相应地更改了问题的标题。你所说的»向量的底层数组«?@CoryKramer到底是什么意思?这不是因为向量重新分配。添加数据保留(1)可防止重新分配,但问题仍然存在。真正的问题是,指向临时对象的指针存储在向量中,一旦临时对象被销毁,值就会发生变化。为了增加乐趣,假设您有{1,2,3},获取指向3的指针,然后
擦除
2。。读取指针处的值,可能仍然会得到3,即使向量现在包含{1,3},并且指针指向用于容纳3的位置。您可能甚至不知道自己犯了错误,直到您将另一个数字推回并覆盖指向的数字element@JoachimW
条目(97)
CachingVector() {
    data_.reserve(1); // prevent reallocation
    resize();
    data_.at(0).cached.info("GET");
}
destroyed 00000000001AF588
RSZ: this=00000000001AF588, i=97
GET: this=00000000001AF588, i=-858993460
Entry(const Entry& rhs) : cached(this), my_i(rhs.my_i) {}
Entry& operator=(const Entry& rhs) { my_i = rhs.my_i; return *this; }