initializer_list和默认构造函数重载决策

时间:2012-01-26 15:29:13

标签: c++ c++11

#include <initializer_list>
#include <iostream>
using namespace std;

struct Y {};

struct X
{
    X(initializer_list<Y>) { cout << "yay" << endl; }
    explicit X() { cout << "boo" << endl; }
};

X f()
{
    return {};
}

int main()
{
    f();

    return 0;
}

打印出“boo”。为什么不打印出“yay”?

无论如何要区分以下两种结构:

  1. X()
  2. X{}
    1. return X();
    2. return {};
    3. void g(const X&)
      
      1. g(X())
      2. g({})
      3. 感谢。

4 个答案:

答案 0 :(得分:5)

  

无论如何要区分以下两种结构:

没有。它们不是不同的结构。

{}构造函数语法的主要目的是引入统一初始化,使初始化在任何地方都相同。如果他们之间存在差异,那就不一致了。

如果要使用空的初始化列表构造函数,则必须声明您正在显式传递初始化列表。像这样:return initializer_list<Y>{};当然,统一初始化的另一个目的是不必输入类型名,所以你可以用return {{}};

实现同样的效果

答案 1 :(得分:5)

return {};将始终使用默认构造函数(如果有)。

return X({});return {{}};将从空的初始化列表构建。

答案 2 :(得分:1)

它使用默认构造函数,因为使用{}的列表初始化意味着始终是一种简短的值初始化形式,忽略其他构造函数,即使它们是初始化列表构造函数。

  

无论如何要区分以下两种结构:......

X()始终是值初始化,而X{}仅是值初始化,如果X具有默认构造函数。如果它是聚合,则X{}是聚合初始化(递归地将X的成员初始化为{})。如果它只有初始化列表构造函数而没有默认构造函数,那么X()无效且X{}可能有效

struct A { A(initializer_list<int>); };
A a = A{}; // valid
A b = A(); // invalid

基本上,X{}的作用取决于X是什么。但X()总是初始化值。

  

...或返回X(); vs return {};

微妙的提及......在return {}中,目标是复制列表初始化的,而在return X();中,首先直接初始化X。但即使它是copy-list-initialized,也可以使用explicit默认构造函数,因为值初始化不关心explicit。但是,如果执行return {}并尝试使用显式非默认构造函数,则会出错

struct A {
  explicit A(initializer_list<int>);
};

A f() { return {}; } // error!

struct B { 
  explicit B();
};

B g() { return {}; } // OK

答案 3 :(得分:0)

你可以更明确一点:

return initializer_list<Y>();