我用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 发布于 2016-10-04 22:46:28
您将在for循环中调用vec.push_back(a)。因此,如果向量耗尽空间,它可能会重新分配底层数组。因此,如果以前的元素被复制到新的内存位置,则它们的地址将不再有效。
例如,假设您分配了3个元素并存储了它们的地址。在推回第四个元素后,向量必须重新分配。这意味着前3个元素将被复制到一个新位置,然后第4个元素将被添加到该位置之后。因此,您为前3个存储的地址现在无效。
发布于 2016-10-04 22:46:18
在调用vector<T>::push_back()时,不能保证迭代器(以及引用和对象地址)会被保留。如果新的size()大于当前的capacity(),则将发生重新分配,并且所有元素都将被移动或复制到新位置。
为了避免这种情况,您可以在开始插入之前调用reserve()。
发布于 2016-10-04 23:00:44
std::vector的主要特性之一是它将元素存储在连续内存中(当您在现代CPU上访问向量的项目时,这是非常好的性能)。
这样做的缺点是,当向量的预分配内存已满,而您想要添加一个新项(例如,调用vector::push_back())时,向量必须分配另一个连续的内存块,并将数据从以前的位置复制/移动到新的位置。作为这种重新分配和复制/移动的结果,旧项目的地址可以改变。
如果出于某种原因,您希望保留对象的地址,而不是将这些对象的实例存储在std::vector中,则可以考虑使用指向对象的指针向量。在这种情况下,即使在重新分配之后,对象指针也不会改变。
例如,您可以将shared_ptr用于vector的项和multimap的键:
vector<shared_ptr<const A>> vec;
multimap<shared_ptr<const A>, const double> mymultimap;https://stackoverflow.com/questions/39855248
复制相似问题