2016-01-26 30 views
0

我知道,使用const_cast不會引入未定義的行爲(即它的使用安全),只要您最初的const_cast ing的變量不是被定義爲const,或者它最初被定義爲const,不要修改它的const_cast ed別名。但是,大多數STL容器(例如,std::vector,std::set)也動態地分配它們的內部緩衝區也是公知的。基於這個事實,我認爲將const定義的std::vector放在只讀存儲器中是不可能的。const_cast const STL容器,它是未定義的行爲嗎?

當然,如果上述持有我來給這類STL容器,即使他們定義爲const的假設,例如,:

std::vector<int> const v; 

const_cast通過他們const_cast版荷蘭國際集團他們改變他們別名是合法的,不會導致任何未定義的行爲。

以上假設成立或我錯了嗎?

+7

如果標準說它是UB,那就是UB。優化器使用這個來做各種瘋狂的東西,假設'const'對象不會被修改。 – juanchopanza

+0

注意,在常量向量的情況下,編譯器不需要動態分配內存(_avoiding allocation_ standard子句),事實上,可以將常量向量完全放置在靜態只讀存儲器中。 –

+0

@ 101010我認爲你選擇我的答案作爲「解決方案」有點太快。它還沒有(正如我正在寫這篇文章)對你的問題的真實答案。到目前爲止,我只是解決了動態分配的內存必須是可變的假設。 –

回答

4

C++標準明確指出,通過new const T創建並修改它的對象的丟失const是未定義行爲。

例如,C++ 11標準包含在其§7.1.6.1/ 4這個例子中:在標準

const int* ciq = new const int (3); // initialized as required 
int* iq = const_cast<int*>(ciq); // cast required 
*iq = 4; // undefined: modifies a const object 

實例是非標準的,僅是示例,並且可以是錯誤。例如,在C++ 03中,幾乎所有使用<iostream>的示例都是錯誤的(當時正式需要包含<ostream>,但這不是委員會的意圖),以及C++ 03§中的表達式示例5/4是錯誤的,說這種行爲沒有說明而不是未定義(這可能反映了初衷)。但是,上面的例子是正確的。

這表明動態分配的內存不需要可變:即修改它,可以有未定義的行爲。

然而,例如,創建一個std::string,在構造函數執行期間發生緩衝區分配(如果有),此時對象尚未const,緩衝區未分配爲const。所以緩衝區,如果分配的話,最初並不是const。但是關於這個特殊的例子,std::string可能會使用小緩衝區優化,因爲它直接在對象中使用存儲,然後最初的const(可能分配在只讀存儲器中)。這對於沒有原來const對象可以修改的規則來說是合理的。


除了只讀內存場景之外,UB的基本原理還包括它可以爲編譯器提供優化的可能性。

由於juanchopanza筆記a comment to the question

優化器使用該做的所有類型的,它假定const對象將不會被修改瘋狂的事情。

通過修改最初的const對象來打破優化器的假設可能會產生災難性的和實際上不可預測的後果。