首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我的对象在向量中的地址发生了变化

我的对象在向量中的地址发生了变化
EN

Stack Overflow用户
提问于 2016-10-04 22:43:26
回答 3查看 2.5K关注 0票数 2

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

代码语言:javascript
复制
//[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;

结果:

代码语言:javascript
复制
test1: 0x7f6a13ab4000  
test1: 0x7f6a140137c8  
test2 :0x7f6a14013000  
test2 :0x7f6a140137c8  
EN

回答 3

Stack Overflow用户

发布于 2016-10-04 22:46:28

您将在for循环中调用vec.push_back(a)。因此,如果向量耗尽空间,它可能会重新分配底层数组。因此,如果以前的元素被复制到新的内存位置,则它们的地址将不再有效。

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

票数 6
EN

Stack Overflow用户

发布于 2016-10-04 22:46:18

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

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

票数 4
EN

Stack Overflow用户

发布于 2016-10-04 23:00:44

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

这样做的缺点是,当向量的预分配内存已满,而您想要添加一个新项(例如,调用vector::push_back())时,向量必须分配另一个连续的内存块,并将数据从以前的位置复制/移动到新的位置。作为这种重新分配和复制/移动的结果,旧项目的地址可以改变。

如果出于某种原因,您希望保留对象的地址,而不是将这些对象的实例存储在std::vector中,则可以考虑使用指向对象的指针向量。在这种情况下,即使在重新分配之后,对象指针也不会改变。

例如,您可以将shared_ptr用于vector的项和multimap的键:

代码语言:javascript
复制
vector<shared_ptr<const A>> vec;

multimap<shared_ptr<const A>, const double> mymultimap;
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39855248

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档