时间:2019-03-17 标签:c++: calling constructors via curly braces?

标签 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);
}

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

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

最佳答案

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

首先,您可以通过不同的方式构造类型,所有这些都在此处描述: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:

When objects of non-aggregate class type T are list-initialized (8.5.4), overload resolution selects the constructor in two phases:

  • Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class T and the argument list consists of the initializer list as a single argument.
  • If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list.

If the initializer list has no elements and T has a default constructor, the first phase is omitted. In copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed.

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

§8.5.4 List-initialization

(3.4) Otherwise, if T is a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution ([over.match], [over.match.list]). If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed.

关于时间:2019-03-17 标签:c++: calling constructors via curly braces?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60195765/

相关文章:

java - spring或servlet请求范围问题

perl - 'Exporter'、 'use vars' 和 'local' 之间的交互

c++ - SFML 在实现绘制函数时从派生类转换不明确

c++ - 如何干净地创建类型安全的枚举参数

javascript - Phaser3 + ES6 类 : how to keep the scope from create to update

c# 发出动态方法委托(delegate)以加载参数化构造函数问题

c++ - 尝试学习C++构造函数,为什么在这个例子中构造函数中有一个冒号?

c++ - FStream 类并使用字符串作为参数

python - 使用 pybind11,如何将我的代码拆分为多个模块/文件?

c++ - 注入(inject)模板构造函数