使用空花括号进行初始化

14

第一次尝试,一切正常:

class Base {
 public:
    Base() {std::cout << "default ctor!\n"; }
};
...
Base b{};
Base b_one = {};

另一种实现方式(添加explicit):

class Base {
 public:
    explicit Base() {std::cout << "default ctor!\n"; }
};
...
Base b{};
Base b_one = {};  // error! Why?

我在cppreference上看到,在这两种情况下,都将使用默认初始化,并且没有区别。

从列表初始化:

否则,如果花括号初始化列表为空,而T是具有默认构造函数的类类型,则执行值初始化。

从值初始化:

如果T是没有默认构造函数或具有用户提供或已删除的默认构造函数的类类型,则对象被默认初始化;

1个回答

19
我在cppreference上读到,两种情况下都会使用默认初始化,并没有区别。
不,它们并不相同。确切地说,Base b{};直接列表初始化, 而 Base b_one = {};复制列表初始化; 对于复制列表初始化,只能调用非explicit构造函数。
(重点在于)
  • 直接列表初始化(考虑显式和非显式构造函数

  • 复制列表初始化(显式和非显式构造函数都会被考虑,但只能调用非显式构造函数


1
哦,谢谢。这个问题太简单了 ;) 那么你能帮忙回答另一个问题吗?当我们将已初始化的变量b_one = {}赋值时会发生什么? - Gusev Slava
5
如果 Base 的默认构造函数不是 explicit,则会尝试调用 operator=。此时 {} 会被隐式转换为 Base,然后调用拷贝赋值运算符 (Base::operator=(const Base&))。如果默认构造函数是 explicit,则会失败,因为隐式转换失败。 - songyuanyao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接