C ++:通过大括号调用构造函数?

c++ : calling constructors via curly braces?

本文关键字:调用 构造函数      更新时间:2023-10-16
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);
}

如果有的话,get_a1()get_a2()有什么区别?

return {value};怎么称呼?(我想"通过大括号调用构造函数"不是引用此的正确方式(

在您的情况下,根本没有区别。但是如果你稍微修改一下你的代码,就会有一个明显的区别!

首先,你可以用不同的方式构造你的类型,所有描述都在这里描述:

区别就来了,如果你的类也提供了一个接受std::initializer_list的构造函数。

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

class A 
{   
public:
A(int value):value_(value){ std::cout << "int" << std::endl;}
A(const std::initializer_list<int>& ){ std::cout << "list" << std::endl;}
void print()
{   
std::cout << value_ << std::endl;
}   
private:
int value_;
};  
A get_a1(int value)
{   
std::cout << "()" << std::endl;
return A(value);
}   
A get_a2(int value)
{
std::cout << "{}" << std::endl;
return {value};
}

int main()
{   
A a1 = get_a1(1);
a1.print();
A a2 = get_a2(2);
a2.print();
}   

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

为什么在标准中描述:

§13.3.1.7 [over.match.list]/p1:

当非聚合类类型的对象T进行列表初始化时 (8.5.4(,重载解析分两个阶段选择构造函数:

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

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

此外,初始值设定项列表构造函数不允许缩小范围!

§8.5.4 列表初始化

(3.4( 否则,如果 T 是类类型,则考虑构造函数。适用的 枚举构造函数,并通过重载选择最佳构造函数 分辨率([over.match], [over.match.list](。如果缩小转换范围 (见下文(是转换任何参数所必需的, 程序格式不正确。