C++返回向量.AT.()地址更改

C++返回向量.AT.()地址更改,c++,vector,C++,Vector,为什么元素的地址是乒乓球 我有这样的想法: std::vector<double> foo(...); int main(){ std::vector<double> x; x.assign(1,0.0); x = foo(...); print &x.at(0); // 0x607210 x = foo(...); print &x.at(0); // 0x607240 x = foo(...

为什么元素的地址是乒乓球

我有这样的想法:

std::vector<double> foo(...);

int main(){
    std::vector<double> x;
    x.assign(1,0.0);
    x = foo(...);
    print &x.at(0); // 0x607210

    x = foo(...);
    print &x.at(0); // 0x607240

    x = foo(...);
    print &x.at(0); // 0x607210
}
为什么元素的地址是乒乓球?x的基址保持不变,值x.at0始终正确。这里有一个我不理解的微妙之处。

foo函数返回一个新向量。由于结果是一个r值,它将被移动指定给x。由于每个新向量都有各自不同的缓冲区,因此在每次移动分配之后,x的缓冲区也将不同

一个缓冲区不能与另一个现有缓冲区共享其地址,并且返回的r值和x都有重叠的生存时间,因此缓冲区地址必须更改。但是一个不同的缓冲区可以有一个先前被破坏的缓冲区的地址,这就是为什么你观察到的重复是可能的。

x=foo正在给x分配一个std::vector。根据,operator=总是使指向其元素的指针、引用和迭代器无效。预计元素的地址将发生变化。这些乒乓球只是你碰巧观察到的行为。这不是什么可以信赖的东西


考虑一下在这种情况下分配给std::vector意味着什么。move赋值操作符将用foo返回的std::vector的底层数据替换x的底层数据。新数组不可能与它要替换的数组具有相同的地址。

发布真实的可编译代码。向量的地址与包含的数据的地址有什么关系?将向量指定给向量。你认为会发生什么?地址交替的原因是,旧向量被销毁后,它的内存变为可用,而碰巧下一个向量使用了该内存。@Barmar说得好。我用自己的措辞在答案中添加了这一点。将foo更改为const vectorfoo;强制副本分配,从而保留x元素的地址?@Rob是的,它将强制副本分配。x元素的地址是否被保留,取决于foo返回的内容。向量是否大于x的容量?如果两个分配器实例都使用默认的分配器实例,那么分配器实例是否等效?在这些情况下,无法保留地址。否则,该标准似乎未规定该行为: