2017-04-10 84 views
0

我搜索了互聯網和StackOverflow關於const_cast <>以及它造成的困惑,我發現有用的東西,但是我仍然有一個問題。當const不是一個明確的?

考慮到這種代碼,

#include <iostream> 
using namespace std; 

int main(void) 
{ 
    const int a = 1; 
    int *p = const_cast<int*>(&a); 
    *p = 2; 

    cout << "value a="<< a << endl; 
    cout << "value *p=" <<*p << endl; 
    cout << "address a=" <<&a << endl; 
    cout << "address p=" <<p << endl; 
} 

的輸出是:

值= 1
值* p = 2時
地址= 0x69fef8
地址P = 0x69fef8

我發現這樣的代碼ma y導致未定義的行爲。 (例如編譯器可能會「與1小號的全部更換a優化,因此劇組已經沒有意義了)

我也發現了這句話:

如果你拋棄的常量性一個已明確聲明爲 的對象聲明爲const,並嘗試對其進行修改,結果爲 未定義。

但是,如果拋棄了不是顯式聲明爲const的 的對象的常量,則可以安全地對其進行修改。

和此:

注意,C++提供const_cast刪除或添加常量性到 變量。但是,在去除常量時,它應該用於將參數/指針的常量從名稱不是 的常量中刪除。現在

,考慮到上面的代碼以下修改:

int b = 1; 
const int a = b; 

輸出爲:

值= 2
值* p = 2時
地址= 0x69fef4
地址p = 0x69fef4

我明白:

aint a = 1是在編譯時處理的常量表達式。
a in int a = b不是,它只能在運行時處理。

如所述here

我的問題:

當是常量的聲明明確,當不是嗎?它怎麼可能最初是非常量?

+1

*「int a = 1」中的'a'是一個在編譯時處理的常量表達式。「* - Nope。在C++中沒有這樣的保證。只有'constexpr'變量提供了這樣的保證。 – WhiZTiM

+0

@WhiZTiM除非你憤世嫉俗,並且閱讀了一個實現定義的複雜性限制,那麼'constexpr'必須爲0,因此'constexpr'是毫無價值的。 – nwp

+0

不,「不會導致未定義的行爲」 - 「**有**未定義的行爲」。 –

回答

5

一個簡單的反例,其有效:

void foo(const int *a) {   // Pointer-to-const here 
    int *p = const_cast<int*>(a); 
    *p = 2; 
} 

int main() { 
    int a = 1;      // But underlying object is not const 
    foo(&a); 
} 
+0

我認爲第二行應該是:'int * p = const_cast (a);' – Shadi

+0

@Shadi - 好,趕快,謝謝! –

3

在這個例子中:

int b = 1; 
const int a = b; 

a是頂層constb不是。

如果你將它們傳遞給這樣的功能:

void f(const int &i){ 
    const_cast<int &>(i)++; 
} 

然後f(a)是非法的,因爲你正在改變一個頂級const對象,也被宣佈爲const從一開始的對象,因此你的程序會顯示未定義的行爲。
另一方面,f(b)會沒事的,因爲b開始不是const,然後通過參數轉換得到const加入它,然後再去掉const。由於b開始可以修改,因此可以通過刪除已添加的const來修改它。

+0

這兩個工作正常。除非你的意思是非法,即使預期的結果是正確的。在這種情況下,問題中的第二個代碼也是非法的。不過,我已經在某處讀過,沒關係。不好的是'int a = 1'然後'f(a)'。你怎麼看? – Shadi

+0

@Shadi你可能會感到不幸,編譯器會決定做你想做的事情,但根據標準,它是未定義的行爲,改變編譯器或編譯器優化可能會破壞代碼。我不知道你指的是什麼第二個代碼。 – nwp

相關問題