2015-04-26 47 views
5

我知道拋棄const應該小心謹慎,並且任何嘗試從最初的const對象中刪除const對象,然後修改對象會導致未定義的行爲。如果我們想要刪除const -ness,那麼我們可以調用一個不會修改對象的非const函數呢?我知道我們實際上應該標記這樣的功能const,但假設我使用的「壞」代碼沒有const版本可用。通過const_cast刪除const並調用一個不修改結果對象的非const函數是否安全?

因此,總結一下,下面的代碼是「安全的」?我的猜測是,只要你不修改對象就沒問題,但我不是100%確定的。

#include <iostream> 

struct Foo 
{ 
    void f() // doesn't modify the instance, although is not marked const 
    { 
     std::cout << "Foo::f()" << std::endl; 
    } 
}; 

int main() 
{ 
    const Foo foo; 
    const_cast<Foo&>(foo).f(); // is this safe? 
} 
+1

無論標準允許的事實如已回答,我會說它既不安全也不好。 – hvd

+0

@ hvd爲什麼只讀操作不安全? – Barry

+1

@Barry這不是重點。該成員函數可以稍後修改,以便意外調用UB。 – Columbo

回答

3

相對於const_cast未定義行爲是由C++ 11標準的§3.8/ 9定義(§3.8是「對象壽命」):

創建在一個新的對象具有靜態,線程或自動存儲持續時間的const對象佔用的存儲位置,或者在此對象過去佔用的存儲位置結束之前導致未定義的行爲。

and §7.1.6.1/ 4(§7.1.6。圖1是「 的CV-限定符 」)

除了任何類成員宣告mutable(7.1.1)可以被修改,任何試圖在其壽命期間修改const 對象(3.8)導致未定義的行爲。

換句話說,你如果修改原本const對象獲得UB,否則沒有。

const_cast本身不會引入UB。


有另外在§5.2.11/ 7的非標準的注意,取決於類型」通過從const_cast獲得的指針或引用的寫入「,可以具有未定義的行爲。

這個非規範性附註非常含糊以至於它有它自己的非規範性腳註,這就解釋了「 const_cast不限於丟棄const限定符的轉換。 」。

但是,仍然有這種澄清,我沒有想到任何情況下寫可以定義良好或不取決於類型,即我沒有理解這個筆記。這裏另外兩個答案的重點是「這個字寫」,這是通過§3.8/ 9進入UB-land的必要條件,是的。對我來說很腥的方面是「,這取決於」的類型,這似乎是該筆記的重要部分。


1)除了在對其他非const_cast - 相關的東西UB-規則進入遊戲,例如將一個指針取消,該指針後來在除typeid表達式以外的其他上下文中被解除引用。

+0

還有:7.1.6.1「除了任何聲明mutable的類成員(7.1.1)可以被修改外,任何在其生命週期(3.8)修改const對象的嘗試都會導致未定義的行爲。 –

+0

@CharlesBailey:謝謝,我會補充一點。完成。 –

+0

「取決於類型」在定義對象時使用的類型是有意義的。定義中使用的const限定符是類型的一部分,是否允許修改取決於是否使用了該限定符。 – hvd

6

這個特殊的例子恰好是安全的(具有明確定義的行爲),因爲沒有寫入到被聲明const的對象。

+0

所以只要沒有「寫」它是安全的,對吧?我也這麼想。 – vsoftco

+0

確切地說,當構成對象表示的字節被寫入時發生寫入。 –

6

我們有這在[dcl.type.cv]:

除了任何類成員聲明mutable(7.1.1)可以被修改,任何試圖在其壽命期間修改const對象(3.8 )導致未定義的行爲。

而且還有一個音符(非標準)的[expr.const.cast]其中指出:

[注:根據對象的類型,一個寫操作通過指針,左值或指針 來自const_cast的數據成員,該數據成員拋棄const限定符可能會產生未定義的 行爲(7.1.6.1)。 末端音符]

嘗試後const_cast [可]導致未定義的行爲來修改一個對象或寫操作。在這裏,我們沒有寫操作。

相關問題