2017-07-30 117 views
2

這是更多的學術問題,因爲我知道通常要避免const_cast是否可以在數組上使用const_cast來更改元素?

但是我正在研究第3章#27的Thinking in C++,Vol。 1.

創建一個double的double數組和一個volatile的volatile數組。通過每個數組索引 並使用const_cast分別將每個元素轉換爲非常量和非揮發性的 ,併爲每個元素分配一個值。

我看到如何const_cast單瓦爾:

const int i = 0; 
int* j = const_cast<int*>(&i); 

*j = 1; // compiles and runs 

但無法弄清楚如何得到它與一個陣列工作。以下編譯,但會引發'訪問不良'異常,就好像const仍然存在。

const int sz = 10; 
const double cd[sz] {0,1,2,3,4,5,6,7,8,9}; 
volatile double vd[sz] {0,1,2,3,4,5,6,7,8,9}; 

double* cdp = const_cast<double*>(cd); 
double* vdp = const_cast<double*>(vd); 

cdp[0] = 99; // bad access error 

我哪裏錯了?

+0

您不能修改常量。對編譯器說謊並不能使它工作。 – NathanOliver

+5

你的兩個例子都表現出未定義的行爲。 「編譯和運行」是未定義行爲的一種可能表現形式; 「訪問錯誤錯誤」是另一回事。另見:[鼻惡魔](http://www.catb.org/jargon/html/N/nasal-demons.html)。一本表明編寫代碼展示UB是一個好主意的書是,我們可以說,不是一本很好的書來研究C++。 –

+0

'* j = 1; //編譯並運行'..但是什麼'cout << i'和'cout << * j'打印? – txtechhelp

回答

2

請注意:

const int i = 0; 
int* j = const_cast<int*>(&i); 

*j = 1; // UNDEFINED BEHAVIOR - modify actually const data 

您是允許的虛擲,最初聲明爲const常量性修改的對象。編譯器可以將對象(或數組)的內容放在只讀存儲器中,該存儲器在機器中處於較低級別,而不是編譯器。當你寫的時候,它可能會觸發一個錯誤。如果它被聲明爲const,那麼您必須永遠尊重它,否則就會遇到崩潰。

這是只有如果對象最初被聲明爲非const,則可以在拋棄constness後進行修改。 (也就是說,常量是稍後添加的,也許是作爲函數的參考參數。)

爲了舉例,讓我們將您的問題改寫爲至少有效的情況。

// f() takes a reference to an array, but add constness 
void f(const double(&arr)[10]) 
{ 
    // Here it's ok to cast away constness and modify since the 
    // underlying object isn't declared const (though in general a 
    // function doesn't know that about its caller, except in 
    // constrained situations.) 
    double * array = const_cast<double*>(arr); 
    array[1] = 99; 
} 

int main() 
{ 
    // NOTE: array is NOT CONST 
    double arr[10] {0,1,2,3,4,5,6,7,8,9}; 
    f(arr); 
} 

這很好。

+0

好的。感謝您向我展示一個可行的用例。 – bigswifty

+1

這是不正確的。無論指針指向什麼,拋棄任何常量指針的const都是非常好的。你的推理不適用;硬件限制不適用於此類操作。只有UB才能修改一個const對象,並且有可變的子對象。 IOW,你標記爲UB的那條線實際上是完美的;下一行'* j = 1;'是UB。 –

+0

謝謝@HWalters,我在收到提示時收緊了答案中的螺栓。 :) –

相關問題