矢量中对象的地址发生了变化

时间:2016-10-04 14:43:26

标签: c++ c++11

我用A个对象填充了一个向量,然后将这些对象地址存储在multimap [1]中,但是打印消息显示对向量中存储的对象的引用发生了变化[2] 。你明白为什么吗?以及如何避免任何变化。

//[1]
vector<A> vec; 
multimap<const A*, const double > mymultimap;

for (const auto &a : A) {
  double val = a.value();
  vec.push_back(a);
  mymultimap.insert(std::pair<const A*, const double >( &vel.back(), val)); 

  // displaying addresses while storing them    
  cout<<"test1: "<<&vec.back()<<endl;

}

//[2]
// displaying addresses after storing them
for(auto &i : vec)
    cout << "test2: " << &i <<endl;

结果:

test1: 0x7f6a13ab4000  
test1: 0x7f6a140137c8  
test2 :0x7f6a14013000  
test2 :0x7f6a140137c8  

3 个答案:

答案 0 :(得分:5)

您在vec.push_back(a)循环中呼叫for。因此,如果向量空间不足,则向量可以重新分配基础数组。因此,如果先前元素的地址被复制到新的内存位置,则它们的地址不再有效。

例如,假设您分配了3个元素并存储了它们的地址。推回第4个元素后,向量必须重新分配。这意味着前3个元素将被复制到新位置,然后在此之后添加第4个元素。因此,您为前3个存储的地址现在无效。

答案 1 :(得分:3)

当您致电vector<T>::push_back()时,不保证会保留迭代器(以及引用和对象地址)。如果新的size()大于当前capacity(),则会重新分配并移动所有元素或将其复制到新位置。

为避免这种情况,您可以在开始插入之前致电reserve()

答案 2 :(得分:1)

std::vector的一个主要特性是它将其元素存储在连续内存中(当您访问现代CPU上的矢量项时,这非常适合性能)。

缺点是当向量的预分配内存已满并且您想要添加新项目(例如调用vector::push_back())时,向量必须分配另一块连续< / em>内存,并将数据从先前位置复制/移动到新位置。由于这种重新分配和复制/移动,旧项目的地址可能会发生变化。

如果由于某种原因你想要保留对象的地址,而不是在std::vector中存储这些对象的实例,你可以考虑使用指针的向量< / em>到对象。在这种情况下,即使在重新分配之后,对象指针也不会改变。

例如,您可以对shared_ptr项和vector项使用multimap

vector<shared_ptr<const A>> vec;

multimap<shared_ptr<const A>, const double> mymultimap;