2012-01-21 26 views
4

我有以下代碼:const_cast無法正常工作?

const int k=1; 
    int *p=const_cast<int *>(&k); 
    cout<<"k before="<<*p<<endl; 
    *p=10; 
    *const_cast<int *>(&k)=12; 
    cout<<"k after="<<k<<endl; 

輸出是:

k before=1 
k after=1 

爲什麼不常量投在這裏工作?

回答

2

const_cast通常用於/如果您收到const指針,該指針最初並未定義爲const。如果(如您的情況)對象最初定義爲const,試圖修改它會導致未定義的行爲。如果沒有const_cast,編譯器不會讓你嘗試這樣做(代碼不會編譯)。

然而,演員告訴編譯器,你確定你知道你在做什麼,它是非常安全的,所以編譯器只需要閉嘴,做你所說的,而不是給出任何錯誤/警告消息像它通常那樣。不幸的是,在這種情況下,你正在做的是而不是真的很安全,但既然你已經告訴編譯器閉嘴並且這樣做,你不會對它發出任何警告(至少在大多數編譯器中)。

至於你應該做什麼,它歸結於決定你的k是否真的是const。如果您確實需要修改它,則需要將其定義爲正常(非const)變量。如果你想確保只有特定的代碼量小可以修改它,那麼你可以/可以(爲一種可能性),將其變爲私有的小類:現在

class my_int { 
    int k; 
public: 
    my_int() : k(1) {} 

    do_mod() { k = 10; } 

    operator int() { return k; } 
}; 

do_mod可以直接修改k。其他代碼可以使用my_int對象,就好像它是int一樣,但不能修改其值 - 實質上,它的行爲類似於右值。

憑心而論,我也許應該指出的是,如果它真的嘗試做一些鑄造,其他代碼可以修改k值。正如Bjarne所說,C++的保護機制旨在防止事故,而不是有意顛覆。

12

const_cast原因undefined behaviour如果您丟棄const然後寫入該值。不做任何事情都是有效的行爲,正如你在這裏看到的。

在你的具體的例子,什麼可能發生的情況是編譯器看到的是k聲明與const存儲類,知道它不能(法律)的變化,並取代

cout<<"k after="<<k<<endl; 

cout<<"k after="<<1<<endl; 

如果關閉優化,您可能(或不會)得到不同的結果。

鑄造const調用未定義行爲的原因是,編譯器可以自由地進行這樣的優化。如果const變量可以自由轉換爲非const變量並寫入,那麼const對編譯器來說絕對沒有意義。

+5

編譯器可以選擇將'const'對象放在只讀存儲器中,在這種情況下,該程序可能會因訪問衝突而崩潰。 –

+0

如果您從被定義爲const的對象拋棄constness,會導致未定義的行爲。如果你從一個引用指向非代價不太高的對象中去掉const。 –

4

你在做什麼是未定義的行爲。您不能嘗試修改變量const

+2

它實際上是「試圖修改」最初是'const'的對象,它是未定義的行爲,而不是'const_cast'。 –

+0

@BenVoigt我改變了我的回答 –

+1

對象'k'不僅僅是「最初的const」。它是一個常量,它自創建以來一直存在,只要它的生命週期延長,它就會一直存在。您不能嘗試修改* is * const的對象(包括變量)。 –