c++ : calling constructors via curly braces?

谁都会走 提交于 2021-02-07 18:46:12

问题


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

What is the difference between get_a1() and get_a2(), if any ?

How is return {value}; called ? (I guess "calling constructors via curly braces" is not the proper way to refers to this)


回答1:


In your case, there is simply no difference. But if you modify your code a bit, there will be a visible difference!

First of all, you can construct your type in different ways, all described here: initilization

The difference come in, if your class provides also a constructor which takes a std::initializer_list.

See the following code modified/extended to show the difference:

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();
}   

If you run that prog, you will see that using {} will call the constructor with std::initializer_list and using () will use your int constructor.

Why is described here in the standard:

§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.

In addition, initializer list constructors do not allow narrowing!

§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.



来源:https://stackoverflow.com/questions/60195765/c-calling-constructors-via-curly-braces

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!