長的解釋如下,問題在底部。C++自動實現函數和ODR
我的問題具體是指當前的C++草案標準(也是當前的主要標準),找到here。更具體地說,關於成員職能和ODR,第3.2節第6點(第35頁)陳述了each definition of D shall consist of the same sequence of tokens
。
我最近在添加新數據分析時在項目中遇到了以下問題。
我正在寫一個文件A.cpp。我創建了一個小的虛擬結構來存放一些數據。在這個例子中,我將其稱爲Data
。
namespace Example {
struct Data {
//etc
};
//Use Data
};
然而,在花葯文件,B.cpp,已經有一個結構稱爲Data
的Example
命名空間中。編譯器爲這兩個類生成Data::~Data();
,然後調用它們各自成員的析構函數。 B.cpp中的定義包含一個向量,當使用A.cpp中定義的佈局調用Data
結構時,該向量在被破壞時引起爆炸。雖然這兩個結構似乎都能正常工作,沒有編譯時錯誤,但鏈接時鏈接器會選擇一個定義並使用它,而忽略其他定義。 (因此在A.cpp內的Data
物體上引起爆炸)
在GCC或MSVC下不會發出警告。 當啓用優化時,問題不會發生(函數被內聯,沒有鏈接時間混淆)。
我的問題是,該標準只規定行爲未定義If D is a template and is defined in more than one translation unit
。 要麼我誤解了標準,而是讓未定義的行爲默默地發生;或者GCC和MSVC都默默地接受他們不應該的東西(並且應該拒絕產生輸出或發出警告)(目前的情況是未定義的,而且沒有診斷的行爲不一致)。
是否有人可以幫助我理解這與在類中未定義的函數的衝突定義(這會導致警告/錯誤)的區別。
這是一個ODR違規行爲,但這種違規行爲是「格式不對,不需要診斷」。編譯器不必告訴你。 – Simple
謝謝,但似乎在3.2點4定義。點6似乎處理成員函數,並沒有說明它是未定義的行爲。 – James
好吧,它是未定義的而不是IFNDR(雖然兩者都是真實的意思)。編譯器生成的成員函數隱式地是'inline',這意味着這兩個函數違反了ODR,因爲您在問題開始時引發了這樣的問題:* D的每個定義都應該包含相同的標記序列*。 – Simple