问题
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
Tare 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
Tand 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
Tand the argument list consists of the elements of the initializer list.If the initializer list has no elements and
Thas a default constructor, the first phase is omitted. In copy-list-initialization, if anexplicitconstructor 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