2015-10-31 84 views
2

我遇到了這個問題,並且想知道它的原因是什麼。C++中結構體與對象屬性和std :: vector的交互

我的代碼如下:

struct node{ 
    bool leaf; 
    std::string label; 
}; 

//in main 
std::vector<node> graph; 
graph.reserve(5); 

現在,如果我嘗試分配 graph[3].leaf = true;, 一切順利。

但是,如果我嘗試做同樣的對象類型,如 graphA[i].label = "01";, 我得到一個分段錯誤。

如果我改變代碼

struct node{ 
    bool leaf; 
    std::string * label; 
}; 

而且分配的內存在載體node每個實例的字符串,我現在可以分配一個值graphA[i]->label沒有問題。

這是爲什麼?任何迴應將不勝感激。

+0

'graph.reserve(5);'=>'graph.resize(5);'應該修復它。你不需要一個指針和'new'。 –

+1

嘗試'graph.at(3)'得到一個更好的錯誤信息 – user463035818

+0

'reserve'只保留,你的向量仍然有零個元素 – user463035818

回答

1

現在,如果我嘗試分配graph[3].leaf = true;,一切順利。

重要的是要強調這只是一個巧合。什麼都行不通 - 你有未定義的行爲因爲你訪問graph[3]當是空的。如果程序立即崩潰,這會讓你發現有什麼錯誤。

是空的,因爲您感到困惑std::vectorreserveresize成員函數。您不會將矢量的元素數設置爲5,您只需要它爲將來至少5個元素準備內部保存的內存。 std::vector甚至可以忽略這個請求。

當你做graphA[i].label = "01";,當然你也有未定義的行爲。

那麼爲什麼第一個版本和指針「修復」(它也調用未定義的行爲)似乎工作正常,而另一個崩潰? C++作爲一種編程語言不區分不同種類的未定義行爲。 任何事情都可能發生;你可能會遇到第一次崩潰和第二次崩潰的情況。這是未定義行爲的本質。

什麼可能發生在這裏的做法是,在boolstd::string*情況下,你都不約而同地寫你的程序是允許寫入到存儲位置,因爲你只是處理一個單一bool或用單指針。在std::string版本中,std::string的所有std::string的自動動態內存管理都是在幕後發生的,因此涉及內存中的更多位置,所以碰巧發生了禁止訪問。

但這只是一個非常具有推測性的理論。如果你確實想知道,調試代碼並進入每個單獨的操作。但請記住,未定義的行爲總是未定義的行爲。

5

現在,如果我嘗試分配graph[3].leaf = true;

你調用未定義的行爲。

具有索引3事實上沒有元件,它具有完全沒有元素。您只有reserve d內存爲向量,但沒有添加任何元素。

可以使用resize加5缺省構造元素:

graph.resize(5); 
相關問題