2014-03-13 61 views
3

怪異的行爲我都知道,使用const_cast一般是壞主意,但我玩了,我跨怪異的行爲,哪裏傳來:與const_cast會

兩個指針具有相同的地址值,但去的時候引用,給出不同的數據值。

有沒有人對此有過解釋?

代碼

#include <iostream> 

int main() 
{ 
    const int M = 10; 

    int* MPtr = const_cast<int*>(&M); 

    (*MPtr)++; 

    std::cout << "MPtr = " << MPtr << " (*MPtr) = " << (*MPtr) << std::endl; 
    std::cout << " &M = " << &M << "   M = " << M << std::endl; 
} 

輸出

MPtr = 0x7fff9b4b6ce0 (*MPtr) = 11 
    &M = 0x7fff9b4b6ce0   M = 10 

回答

2

因此,除「這是未定義的行爲」(這是),編譯器是完全沒有用的事實,M是恆定的,因此不會改變,在評價的cout ... << M << ...,所以可以使用具有立即數10的指令,而不是存儲在M的存儲器中的實際值。 (當然,標準不會說這是如何工作的,不僅僅是「未定義」,而且編譯器能夠在不同情況下選擇不同的解決方案等等,所以如果您修改完全可能會得到不同的結果該代碼使用不同的編譯器,不同版本的編譯器或風向不同的方向吹)。

具有「未定義行爲」的棘手問題的一部分在於它包含的內容「完全符合您的期望」以及「幾乎您所期望的」。如果它發現這是你正在做的事情,編譯器也可以決定啓動俄羅斯方塊。

是的,這是你爲什麼不應該使用const_cast的原因之一。在不就的事情,原本const最起碼的 - 這是確定的,如果你有這些方針的東西:

int x; 

void func(const int* p) 
{ 
    ... 
    int *q = const_cast<int *>(p); 

    *q = 7; 
} 


... 

func(&x); 

在這種情況下,x其實不是常量,它只是成爲常量,當我們把它傳遞給func。當然,編譯器可能仍然認爲在func中沒有被更改,因此你可能會遇到問題....

+0

或者,至少,爲什麼你只應該對實際上* not * const的變量使用'const_cast' ,但是你有一個指向指針的指針。 – Sneftel

+0

const_cast是一個重要的工具,它存在的原因。你只需要知道它是什麼,才能正確使用它。 – shawn1874

+1

當然這是有原因的 - 語言架構師(大部分時間,至少)不只是添加功能,因爲他們喜歡它。不過,我已經成功使用了C++約7年,而不需要使用const_cast。我的一位同事需要這樣做 - 因爲一些被聲明爲'const'的函數需要修改一個成員變量,所以使用const-cast來鑄造'this'是唯一的出路(重新定義函數將會是一個更糟糕的解決方案)。所以,「不應該用」對我來說很好。 –

5

該方案已經未定義bahaviour,因爲你不能改變一個const對象。

從C++標準

4某些其他操作均在本國際 標準描述爲未定義(例如,試圖修改 const對象的效果)。 [注:本國際標準對含有未定義 行爲的程序的行爲沒有要求 。末端注]

+2

在這種情況下,由於你的'M'是常量,輸出行甚至不會檢查什麼號碼存儲在它的地址。它只是一個硬編碼的「print 10」,因爲你已經允許編譯器假設'M'將始終是10. – Sneftel