在繼續閱讀本文之前,請首先閱讀Is there a difference in C++ between copy initialization and direct initialization?,確保你明白它在說什麼。C++複製初始化和直接初始化,奇怪的情況
我會在這裏先總結一下規則(讀取標準n3225 8.5/16,13.3.1.3,13.3.1.4和13.3.1.5),
1)直接初始化,所有構造函數都會被視爲重載設置,重載分辨率將根據重載解析規則選擇最佳分辨率。
2)對於複製初始化和源類型與目標類型相同或從目標類型派生,除了僅將轉換構造函數(構造函數沒有顯式)視爲重載集外,其規則與上述相同。這實際上意味着顯式複製/移動構造函數不會被視爲重載集合。 3)對於上面(2)中未包括的複製初始化情況(源類型與目標類型不同並且不是源自目標類型),我們首先考慮用戶定義的轉換序列,其可以從源類型轉換爲目標類型或(當使用轉換函數時)到其派生類。如果轉換成功,則結果用於直接初始化的目標對象。在本用戶定義的轉換序列中,根據8.5/16和13.3.1.4中的規則,將考慮轉換ctors(非顯式ctors)和非顯式轉換函數。
3.2)結果prvalue將直接初始化爲目標對象,如(1)中列出的規則,參見8.5/16。
好的,對規則來說足夠了,讓我們看看一些奇怪的代碼,我真的不知道我的推理是錯誤的,還是隻是所有的編譯器都是錯誤的。請幫助我,謝謝。
struct A
{
A (int) { }
A() { }
explicit A(const A&) { }
};
struct B
{
operator A() { return 2; }
//1) visual c++ and clang passes this
//gcc 4.4.3 denies this, says no viable constructor available
};
int main()
{
B b;
A a = b;
//2) oops, all compilers deny this
}
在我的理解,對於(1),
operator A() { return 2; }
因爲C++具有函數返回被作爲複製初始化,根據上述規則的規則,2將被首先隱式轉換到A,這應該是確定的,因爲A有一個構造函數A(int)。然後,轉換後的臨時值將被用來直接初始化返回的對象,這應該也可以,因爲直接初始化可以使用顯式拷貝構造函數。所以GCC是錯誤的。
對於(2),
A a = b;
在我的理解,首先b爲隱式轉換爲A,由運營商A(),然後將轉換後的值將用於直接初始化,這可當然要調用顯式拷貝構造函數?因此,這應該通過編譯和所有編譯器都是錯誤的?請注意,對於(2),visual C++和clang都有類似於 的錯誤「錯誤,無法從B轉換爲A」,但如果我在A的複製構造函數中刪除顯式關鍵字,則錯誤不見了..
感謝您的閱讀。
編輯1
因爲有人還是沒有得到我的意思,我引述8.5/16以下的標準,
否則(即,對剩餘的 複印通初始化情況), 用戶定義的轉換序列 可以從源類型轉換爲 目標類型或(當使用 轉換功能時)轉換爲 的派生類如13.3.1.4中所述列舉爲 ,並且最好的 通過分解(13.3)的過載 來選擇。如果轉換 無法完成或不明確,則 初始化格式不正確。使用 初始化程序表達式作爲其參數 調用所選的 函數;如果該函數是構造函數 ,則該調用將初始化 暫時的目標類型的cv未合格版本 版本。 臨時是一個prvalue。的 呼叫的結果(這是臨時用於 構造情況下)隨後被用於 直接初始化,根據上述規則 ,那是 目的地的 複製初始化的對象。在某些情況下, 的執行被允許爲 通過構造 直接初始化對象的 直接初始化來消除此 直接初始化中固有的複製;見 12.2,12.8。
請注意,它確實提到在用戶定義的轉換後直接初始化。這意味着,根據我的理解,以下代碼應遵守規則,正如我所評論的,這是由clang,coomeau online,visual C++所證實的,但GCC 4.4.3不能同時滿足(1)和(2)的要求。雖然這是一個奇怪的規則,但它遵循標準的推理。
struct A
{
A (int) { }
A() { }
explicit A(const A&) { }
};
int main()
{
A a = 2; //1)OK, first convert, then direct-initialize
A a = (A)2; //2)oops, constructor explicit, not viable here!
}
Comeau Online以書面形式接受整個代碼片段。 –
好的,謝謝。這給了我一些信心,我的推理至少不會走向錯誤的方向。^_^ – user534498
@詹姆斯麥克奈利斯:然而,科莫在線拒絕我的答案中的代碼,儘管根據OP的推理它應該被接受。 – AnT