簡體   English   中英

為什么Foo({})調用Foo(0)而不是Foo()?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM