在c++中构造对象时,括号和大括号有什么区别?

8

(){} 构造对象时有什么区别呢?

我认为 {} 只能用于支持 initializer_list 或数组,但当我运行下面的代码片段时感到困惑。

#include <iostream>
using namespace std;
struct S {
    int v=0;
    S(int l) : v(l) {
    }
};


int main()
{
    S s1(12); // statement1
    S s2{12}; // statement2
    cout << s1.v << endl;
    cout << s2.v << endl;
}

语句1正确,因为()是构建对象的基本语法。

我预计语句2将编译失败。我认为{}只能用于数组或initializer_list类型。但实际结果却可以完美编译而不会出错。

我错在哪里了?


1
你错过了统一初始化,如果你从未听说过它,你应该去搜索一下。在C++11中,这是一件大事。 - 463035818_is_not_a_number
1
我个人建议避免这种写法:std::vector<int> v{10, 12} - 你认为它会产生什么结果?使用 std::vector<int> v(10, 12)std::vector<int> v({10, 12}) 更加清晰明了。 - Aconcagua
1个回答

9
对于 S,它们有相同的效果。两者都调用构造函数 S::S(int) 来初始化对象。 S s2{12}; 被视为 列表初始化(自 C++11 以来);S 不是聚合类型,也不是 std::initializer_list,并且没有接受 std::initializer_list 的构造函数,那么

如果前一个阶段没有找到匹配项,则类型 T 的所有构造函数都参与重载决议,针对由花括号括起来的初始化列表中的元素组成的参数集,但限制只允许非缩小转换。

而你认为

我认为 {} 只能用于数组或 initializer_list 类型。

这是不正确的。列表初始化的作用是,例如如果S是聚合类型,则执行聚合初始化;如果Sstd::initializer_list的特化,则它将被初始化为一个std::initializer_list;如果S有一个接受std::initializer_list的构造函数,则它将被优先用于初始化。您可以参考链接此页面以获取更精确的详细信息。

PS:S s1(12);执行直接初始化


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