2016-10-04 32 views
2

我用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 
+1

請添加正確的代碼。 – SergeyA

+1

'(const auto&a:A){' - 那是什麼? – SergeyA

+1

你爲什麼要存放地址?有向量中元素的引用永遠有效(例如'vec [i]'爲第i個元素) – user463035818

回答

3

迭代器(和引用對象不會忽略),不能保證當你調用vector<T>::push_back()被保存下來。如果新的size()大於當前的capacity(),則將發生重新分配並且將所有元素移動或複製到新位置。

爲了避免這種情況,你可以叫你reserve()開始插入之前。

+0

親愛的Krzaq,是的,你是對的,vec.reserve()運作良好。 Regards – cabe

+0

我不是'reserve()'方法的忠實粉絲,就好像稍後有人調用'push_back()'一樣,它可能使指針的「世界」無效。 –

5

你是你for循環中調用vec.push_back(a)。因此,如果空間不足,向量可能會重新分配基礎數組。因此,如果先前元素的地址被複制到新的內存位置,則其地址不再有效。

例如說你分配了3個元素並存儲它們的地址。在推回第四個元素之後,矢量必須重新分配。這意味着前3個元素將被複制到一個新的位置,然後第4個將被添加。因此,您爲前3個地址存儲的地址現在無效。

+0

親愛的CopyKramer,是的,這是你的問題,謝謝你的回答。問候 – cabe

1

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;