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

7
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};如何调用?(我猜“通过花括号调用构造函数”不是正确的方式来引用它)


差不多吧,我猜。根据https://en.cppreference.com/w/cpp/language/initialization的说法,这是一个“大括号初始化列表”。我不太擅长标准语言,所以我会把完整的答案留给那些想深入了解的人。 - DeducibleSteak
2
我想到的两个不同之处是,如果你有一个long value,它可能会在get_a2中警告你;或者如果A有一个std::initializer_list构造函数,get_a1get_a2将使用不同的构造函数。 - François Andrieux
就此而言,return value; 也可以。 - 463035818_is_not_a_number
1个回答

6
在您的情况下,没有任何区别。但是如果您稍微修改代码,就会有明显的区别!
首先,您可以以不同方式构建类型,所有方法都在这里描述:initilization 如果您的类还提供了一个接受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:
当使用列表初始化(8.5.4)非聚合类类型T的对象时,重载决议会通过两个阶段选择构造函数:
最初,候选函数是类T的初始化器列表构造函数(8.5.4),参数列表包括初始化器列表作为单个参数。
如果找不到可行的初始化器列表构造函数,则再次执行重载决议,其中候选函数是类T的所有构造函数,并且参数列表由初始化器列表的元素组成。
如果初始化器列表没有元素并且T具有默认构造函数,则省略第一阶段。在复制列表初始化中,如果选择了显式构造函数,则初始化是非法的。
此外,初始化器列表构造函数不允许缩小转换!
§8.5.4 列表初始化 (3.4)否则,如果T是类类型,则考虑构造函数。逐个枚举适用的构造函数,并通过重载决议([over.match],[over.match.list])选择最佳构造函数。如果需要任何参数的缩小转换(见下文),则程序是非法的。

如果我们扩展OP的示例,可能会有更多的差异,例如,在列表中有多个元素时进行从左到右顺序评估,以及如果类是聚合体,则表现不同。因为OP写了{value}而不是A{value},所以在C++17之前还存在额外的移动构造差异。我确信我忘记了一些东西。 - walnut
1
@walnut,你说得完全正确。我的想法是在不修改太多的情况下提供更多的背景信息。如果只回答原始代码示例,那么简单的答案也已经给出了:没有区别... :-) - Klaus

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