2015-07-20 22 views
2

考慮下面的代碼:爲標準::矢量儲備()不確定行爲

vector<uint8_t> v(1); 
v.reserve(2); 
uint8_t *data = &v.front(); 
data[1] = 0; 

有未定義的行爲(C++ 98,C++ 03,C++ 11)?
如果是,什麼是獲得RAII緩衝區(不使用C++ 11)的最佳途徑?

+0

對所有回答請注意我在這裏使用reserve()not resize()。 – Andy

+3

獲取大小爲2的緩衝區的最佳方式是使用'resize'而不是'reserve'(或者首先將其大小設置爲2) –

+1

對於現實生活中的應用程序,我會先嚐試'vector :: resize '。通常額外的初始化成本並不重要(迄今爲止我從來沒有這樣做)。如果在你的情況下它應該太慢,你仍然可以用'boost :: unique_ptr '去。 –

回答

5

每當v.empty()爲真時,調用v.front()是未定義的行爲。除非是n < v.size(),否則不確定的行爲稱爲v[n]。而且,在保留內存中沒有對象,所以不能將內存視爲對象。載體只guranatees

[data(), data() + size())在有效範圍

和沒有保證有任何較大的有效範圍。 (請注意,data() == &front(),所以這適用於您的代碼。)

+4

請不要在矢量中有一個元素,因此它不是空的。 – Andy

+3

請注意,我不會在矢量上調用[]。 – Andy

+0

但是內存在那裏(?),如果是這樣,它是連續的,並且'uint8_t'不需要構造函數調用(甚至是POD)。更深層次的問題是,「準備金」是否可以在規則下被忽略或延遲。 –

-1

我檢查了C++ 98標準。

這裏是音符儲備():
這是保證不重新分配需要一個電話之後發生的保留(),直到時間插入過程中發生的時候插入會使向量的大小大比最近一次調用reserve()時指定的大小還要小。「

而從注爲「矢量調節劑」:「如果沒有重新分配情況,所有的插入點之前的迭代器和引用保持有效

因此恕我直言,在問題提出的代碼是完全合法的,甚至爲C++ 98。

+0

訪問未初始化的內存也是未定義的行爲。所以「完全有效」是相當多的誇張。 – rubenvb

+0

初始化未初始化的基本類型對象是未定義的行爲嗎? 不知道標準如何說。 – Andy

+0

請考慮以下代碼:「int a;」 訪問'a'是未定義行爲嗎? – Andy