2017-04-05 27 views
1

我花了很多時間去搜索錯誤的原因。 下面是我使用vector來存儲數據的C++程序。我已經看到,當vector增加自我大小,那麼所有的引用都是改變。所以保存對push_back()對象的引用back()對象是愚蠢的,沒有意義。cpp relocate vector

class Test{ 
    public : 
     int wiek; 
}; 

int main(int argc, char **argv) 
{ 
    std::vector<Test> v; 
    std::vector<Test*> vv; 

    for (int i = 0; i < 12; i++) { 
     Test t; 
     t.wiek = 10; 
     v.push_back(t); 
     vv.push_back(&v.back()); 
    } 

    Test& m = v.back(); 

    for (int i = 0; i < 24; i++) { 
     Test t; 
     t.wiek = 123; 
     v.push_back(t); 
     vv.push_back(&v.back()); 
    } 

    for (int i = 0; i < 36; i++) { 

     std::cout<<"vv.at(i)->wiek : "<<vv.at(i)->wiek<<"\n"; 
    } 

    // vv.at(i)->wiek : 1619638984 
    // vv.at(i)->wiek : 167838876 
    // vv.at(i)->wiek : 167838896 
    // vv.at(i)->wiek : 167838900 
    // vv.at(i)->wiek : 167839152 
    // vv.at(i)->wiek : 167839156 
    // vv.at(i)->wiek : 167839160 
    // vv.at(i)->wiek : 167839164 
    // vv.at(i)->wiek : 167838872 
    // vv.at(i)->wiek : 167838876 
    // vv.at(i)->wiek : 167838880 
    // vv.at(i)->wiek : 167838884 
    // vv.at(i)->wiek : 167838888 
    // vv.at(i)->wiek : 167838892 
    // vv.at(i)->wiek : 167838896 
    // vv.at(i)->wiek : 167838900 
    // vv.at(i)->wiek : 123 
    // vv.at(i)->wiek : 123 
    // vv.at(i)->wiek : 123 
    // vv.at(i)->wiek : 123 
    // vv.at(i)->wiek : 123 
    // vv.at(i)->wiek : 123 
    // vv.at(i)->wiek : 123 
    // vv.at(i)->wiek : 123 
    // vv.at(i)->wiek : 123 
    // vv.at(i)->wiek : 123 
    // ... 
    // 
    return 1; 
} 

我有權利嗎?

+2

你有什麼權利?你的困惑在哪裏?你說你已經知道你在做什麼使參考無效。 – NathanOliver

+1

@Eddge不完全。他們將一個局部變量插入矢量(複製),然後保存添加的矢量元素位置的地址。類似但不同於直接存儲自動存儲變量的地址。 – crashmstr

+0

@crashmstr你是正確的感謝糾正。 – Eddge

回答

0

正確,你在做什麼與你的載體不完全合理。當你調用push_back()並且向量的大小發生變化時;有一個自動重新分配整個向量的存儲。如此可能,之前添加的元素可能不再存在於其原始地址。

對此的快速解決方案是預先分配您希望使用v.resize()的所有索引。所以下面的代碼應該可以工作:

#include <vector> 
#include <iostream> 

class Test{ 
    public : 
     int wiek; 
}; 

int main(int argc, char **argv) 
{ 
    std::vector<Test> v; 
    std::vector<Test*> vv; 

    v.resize(36); 

    for (int i = 0; i < 12; i++) { 
     Test t; 
     t.wiek = 10; 
     v.push_back(t); 
     vv.push_back(&v.back()); 
    } 

    Test& m = v.back(); 

    for (int i = 0; i < 24; i++) { 
     Test t; 
     t.wiek = 123; 
     v.push_back(t); 
     vv.push_back(&v.back()); 
    } 

    for (int i = 0; i < 36; i++) { 

     std::cout<<"vv.at(i)->wiek : "<<vv.at(i)->wiek<<"\n"; 
    } 

// vv.at(i)->wiek : 10 
// vv.at(i)->wiek : 10 
// vv.at(i)->wiek : 10 
// vv.at(i)->wiek : 10 
// vv.at(i)->wiek : 10 
// vv.at(i)->wiek : 10 
// vv.at(i)->wiek : 10 
// vv.at(i)->wiek : 10 
// vv.at(i)->wiek : 10 
// vv.at(i)->wiek : 10 
// vv.at(i)->wiek : 10 
// vv.at(i)->wiek : 10 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 
// vv.at(i)->wiek : 123 

    return 0; 
} 

但是,如果你不知道最終尺寸是什麼。在將其所有元素的地址分配給「vv」之前,您必須先創建「v」向量的全部。

+1

你可以使用'std :: list'來代替。 http://en.cppreference.com/w/cpp/container/list「添加,刪除和移動列表中的元素或跨幾個列表不會使迭代器或引用無效。」 – Ceros

+0

@Ceros True,更改容器類型也會起作用。然而,我的印象是,這個問題是關於向量的行爲,而不是解決源代碼問題?這是一個相當奇怪的措辭原始問題。 – Darkblue

1

如果您需要允許隨機訪問的容器並確保在容器增長時不會使項目引用無效,請使用std::deque