[英]Why does Foo({}) invoke Foo(0) instead of Foo()?
由代碼中的clang 3.5.0和gcc 4.9.1生成的可執行文件
#include <iostream>
struct Foo
{
Foo() { std::cout << "Foo()" << std::endl; }
Foo(int x) { std::cout << "Foo(int = " << x << ")" << std::endl; }
Foo(int x, int y) { std::cout << "Foo(int = " << x << ", int = " << y << ")" << std::endl; }
};
int main() // Output
{ // ---------------------
auto a = Foo(); // Foo()
auto b = Foo(1); // Foo(int = 1)
auto c = Foo(2, 3); // Foo(int = 2, int = 3)
auto d = Foo{}; // Foo()
auto e = Foo{1}; // Foo(int = 1)
auto f = Foo{2, 3}; // Foo(int = 2, int = 3)
auto g = Foo({}); // Foo(int = 0) <<< Why?
auto h = Foo({1}); // Foo(int = 1)
auto i = Foo({2, 3}); // Foo(int = 2, int = 3)
}
表現為評論。
從cppreference:cpp / language / list初始化 :
[...] T( { arg1, arg2, ... } ) (7) [...]
類型T對象的列表初始化的效果是:
如果
T
是聚合類型,則執行聚合初始化。否則,如果braced-init-list為空且
T
是具有默認構造函數的類類型,則執行值初始化。[...]
我斷定Foo({})
應該調用默認構造函數。
錯誤在哪里?
默認構造函數僅適用於使用一對大括號的情況:
auto a = Foo(); // Foo()
auto b = Foo{}; // Foo()
Foo({})
只會調用帶有空列表作為參數的構造函數,copy-list-initialize選擇任何構造函數的參數。 [dcl.init] / 16:
如果目標類型是(可能是cv限定的)類類型:
- 如果初始化是直接初始化[...],則考慮構造函數。 列舉了適用的構造函數(13.3.1.3),並通過重載解析(13.3)選擇最佳構造函數。 調用所選的構造函數來初始化對象,初始化表達式或表達式列表作為其參數。 如果沒有構造函數適用,或者重載決策是不明確的,則初始化是錯誤的。
你有一個參數:空的braced-init-list。 有一個列表初始化序列將{}
轉換為int
因此構造函數Foo(int)
由重載Foo(int)
選擇。 該參數初始化為零,因為{}
意味着值初始化 ,對於標量,這意味着零初始化 。
cppreferences文檔中也沒有錯誤:對於(7),它表示
7)在函數化轉換表達式或其他直接初始化中,使用braced-init-list作為構造函數參數
這顯然導致與上述引用相同的結果:使用(empty)braced-init-list調用構造函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.