c++:通过花括号调用构造函数?

Vin*_*nce 7 c++ constructor scope return

class A 
{
    int value_;
    public:
    A(int value):value_(value){}
};

A get_a1(int value)
{
    return A(value);
}

A get_a2(int value)
{
    return {value};
}


int main()
{
    A a1 = get_a1(1);
    A a2 = get_a2(2);
}
Run Code Online (Sandbox Code Playgroud)

get_a1()和之间有什么区别get_a2()(如果有的话)?

怎么return {value};称呼?(我猜“通过大括号调用构造函数”不是引用此内容的正确方法)

Kla*_*aus 6

就你而言,根本没有区别。但如果你稍微修改一下你的代码,就会有明显的差异!

\n\n

首先,您可以通过不同的方式构造您的类型,所有这些都在这里描述:初始化

\n\n

如果您的类还提供了一个采用std::initializer_list.

\n\n

请参阅以下修改/扩展的代码以显示差异:

\n\n
class A \n{   \n    public:\n        A(int value):value_(value){ std::cout << "int" << std::endl;}\n        A(const std::initializer_list<int>& ){ std::cout << "list" << std::endl;}\n        void print()\n        {   \n            std::cout << value_ << std::endl;\n        }   \n    private:\n        int value_;\n};  \n\nA get_a1(int value)\n{   \n    std::cout << "()" << std::endl;\n    return A(value);\n}   \n\nA get_a2(int value)\n{\n    std::cout << "{}" << std::endl;\n    return {value};\n}\n\n\nint main()\n{   \n    A a1 = get_a1(1);\n    a1.print();\n    A a2 = get_a2(2);\n    a2.print();\n}   \n
Run Code Online (Sandbox Code Playgroud)\n\n

如果运行该程序,您将看到 using{}将调用构造函数std::initializer_list,并且 using()将使用您的int构造函数。

\n\n

标准中描述了为什么:

\n\n
\n

\xc2\xa713.3.1.7 [over.match.list]/p1:

\n\n

当非聚合类类型的对象T被列表初始化时\n (8.5.4),重载决策分两个阶段选择构造函数:

\n\n
    \n
  • 最初,候选函数是类的初始化列表构造函数 (8.5.4) T,参数列表由初始化列表作为单个参数组成。
  • \n
  • 如果找不到可行的初始值设定项列表构造函数,则再次执行重载解析,其中候选函数都是类的构造函数T,参数列表由初始值设定项列表的元素组成。
  • \n
\n\n

如果初始值设定项列表没有元素并且T具有默认构造函数,则忽略第一阶段。在复制列表初始化中,如果explicit选择了构造函数,则初始化的格式不正确。

\n
\n\n

此外,初始化列表构造函数不允许缩小范围!

\n\n
\n

\xc2\xa78.5.4 列表初始化

\n\n

(3.4) 否则,如果 T 是类类型,则考虑构造函数。枚举适用的构造函数,并通过重载解析([over.match]、[over.match.list])选择最好的构造函数。如果需要缩小转换\n(见下文)来转换任何参数,则\n 程序格式错误。

\n
\n