2011-08-08 141 views
7

下面的代碼編譯的以及都與海灣合作委員會(4.2-4.6),並與鏘(2.1),但是當我運行可執行它給了我「總線錯誤:10」。我不明白原因。的const_cast靜態const成員

#include <iostream> 

struct A 
{ 
    static int const v; 
    A() { ++*const_cast<int *>(&A::v); } 
}; 

int const A::v = 0; 

int main(int argc, char * argv[]) 
{ 
    A a, b, c; 
    std::cout << a.v << std::endl; 

    return 0; 
} 
+3

我非常肯定,修改你聲明const的東西是未定義的行爲,但我相信有人可以挖掘出精確的語句。 –

+3

+1提供一個最小的完整樣本程序。有關更多信息,請參閱http://sscce.org/。 –

回答

12

我認爲相關的報價是:

§ 7.1.6.1 (4) from N3242:

Except that any class member declared mutable can be modified, any attempt to modify a const object during its lifetime results in undefined behavior.

的例子說明了使用const_cast點。正如James指出的那樣:引用可以在C++ 03標準的§7.1.5中找到。

稍微詳細一點:該語言規則允許編譯器在聲明const時使用只讀內存(如果它在目標架構上可用)。沒有這個規則const-總是可以放棄而不用擔心任何後果,並且使用它只會是開發者紀律問題。你至少可以告訴人們他們在調用UB,這通常是一種很好的威懾力量。 const_cast本身沒什麼關係,因爲你怎麼欺騙編譯器讓你操作const對象並不重要。

4

因爲你不允許修改聲明爲const變量。

2

我沒有對實際問題的解決方案。我可以說,不要使用const_cast,除非目的是從非const成員函數中調用const成員函數,並將const結果(使其成爲非const成員函數的可變結果)爲「const_cast」。

但我有改進設計的建議:

class A 
{ 
private: 
    static int v; 
public: 
    A() { ++v; } 
    static int get_v() { return v; } 
}; 

int A::v = 0; 

int main(int argc, char * argv[]) 
{ 
    A a, b, c; 
    std::cout << a.get_v() << std::endl; 

    return 0; 
} 
1

的問題是這一行:

static int const v; 

因爲你宣佈它常量時,const_cast會導致一個未定義的行爲 - 你如果您遇到了總線錯誤(這是我係統中的分段錯誤),那麼您很幸運。

聲明其非const,你可以調用的const_cast它沒有問題。

2

僅僅因爲你已經拋棄常量,並不意味着你會以書面形式向存儲成功。

所有這一切const_cast<T>確實是從編譯器的角度來看,除去變量的常量性。這可以讓編譯器繼續併發出代碼寫入變量。但是在運行時,如果編譯器/鏈接器碰巧把變量放在只讀存儲器中,那麼不管你如何施放它,硬件都會阻止你在那裏寫入數據。

6

5.2.11.7:

Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member resulting from a const_cast that casts away a const-qualifier) may produce undefined behavior (7.1.5.1)

在你的情況,你想修改爲只讀段數據。

+1

這是一個非規範性說明(即僅供參考)。規範性文本在參考的§7.1.5.1中。 –

+0

草案中的§7.1.6.1。看到我的答案。 – pmr

+1

@pmr:對,因爲C++ 0x規範添加了一個定義'constexpr'的子句。 –

2

基本上,如果一個變量聲明const,編譯器允許發射的結果,只讀存儲器。以指針/對const對象的引用,然後使用const_cast刪除const可能會導致未定義的行爲。

通常,如果被引用的對象是非const(即使指針/引用是const),則僅使用const_cast纔是安全的。