我打算调用 initializer_list 构造函数,如果存在复制构造函数,则会预先调用它:为什么?
I intend to call initializer_list constructor, and copy constructor is called beforehand if it exists: why?
以下类型具有三个构造函数。请注意,其中一个采用相同类型的元素的初始化列表。
struct Foo {
Foo() {
std::cout << "default ctor" << std::endl;
}
Foo(const Foo&) {
std::cout << "copy ctor" << std::endl;
}
Foo(std::initializer_list<Foo>) {
std::cout << "initializer_list<Foo>" << std::endl;
}
};
在使用 initializer_list 初始化对象时,我惊讶地发现复制构造函数被自动调用的次数与 initializer_list 中的元素一样多。之后,调用 initializer_list 构造函数:
int main()
{
Foo a; // default ctor
Foo b{a, a, a}; // copy ctor + copy ctor + copy ctor + initializer_list<Foo>
return 0;
}
这种行为背后的 reasons/justifications 是什么?请注意,如果 Foo 没有复制构造函数,初始化 Foo b{a, a, a}
显然是完全可能的( initializer_list 构造函数将是唯一被调用的)。
完整代码在这里:http://coliru.stacked-crooked.com/a/f6e28dbb66746aa2
What are the reasons/justifications behind that behavior?
表达式 {a, a, a}
(在您的示例中)构造了一个 std::initializer_list<Foo>
.
该数组的每个元素(是的,您可以像轻量级数组一样使用初始化列表)被构造为对象 a
的 copy。
实际上,class 的 复制构造函数 被调用了三次,以便恰好构造三个副本。
Note that if Foo had no copy constructor, the initialization Foo b{a, a, a} would apparently be perfectly possible (the initializer_list constructor would be the only one called).
这不是真的。如果Foo
"has no copy constructor",编译器会提供一个默认的。所以在那种情况下,复制构造函数仍然会被调用三次,就像前面的例子一样。
你可以证明它只是删除默认的复制构造函数。
根据你的例子:
struct Bar {
// ...
Bar(const Bar&) = delete;
};
这样就没有拷贝构造函数,代码编译不通过,报错:
use of deleted function 'Bar::Bar(const Bar&)'
std::cout << "d : "; Bar d{c, c, c};
确实,无法像往常一样构造初始化列表。
最终结论
这没有什么神秘之处。
你想构造一个 "list" 三对象。编译器必须构造那些从 a
复制的对象。
以下类型具有三个构造函数。请注意,其中一个采用相同类型的元素的初始化列表。
struct Foo {
Foo() {
std::cout << "default ctor" << std::endl;
}
Foo(const Foo&) {
std::cout << "copy ctor" << std::endl;
}
Foo(std::initializer_list<Foo>) {
std::cout << "initializer_list<Foo>" << std::endl;
}
};
在使用 initializer_list 初始化对象时,我惊讶地发现复制构造函数被自动调用的次数与 initializer_list 中的元素一样多。之后,调用 initializer_list 构造函数:
int main()
{
Foo a; // default ctor
Foo b{a, a, a}; // copy ctor + copy ctor + copy ctor + initializer_list<Foo>
return 0;
}
这种行为背后的 reasons/justifications 是什么?请注意,如果 Foo 没有复制构造函数,初始化 Foo b{a, a, a}
显然是完全可能的( initializer_list 构造函数将是唯一被调用的)。
完整代码在这里:http://coliru.stacked-crooked.com/a/f6e28dbb66746aa2
What are the reasons/justifications behind that behavior?
表达式 {a, a, a}
(在您的示例中)构造了一个 std::initializer_list<Foo>
.
该数组的每个元素(是的,您可以像轻量级数组一样使用初始化列表)被构造为对象 a
的 copy。
实际上,class 的 复制构造函数 被调用了三次,以便恰好构造三个副本。
Note that if Foo had no copy constructor, the initialization Foo b{a, a, a} would apparently be perfectly possible (the initializer_list constructor would be the only one called).
这不是真的。如果Foo
"has no copy constructor",编译器会提供一个默认的。所以在那种情况下,复制构造函数仍然会被调用三次,就像前面的例子一样。
你可以证明它只是删除默认的复制构造函数。
根据你的例子:
struct Bar {
// ...
Bar(const Bar&) = delete;
};
这样就没有拷贝构造函数,代码编译不通过,报错:
use of deleted function 'Bar::Bar(const Bar&)'
std::cout << "d : "; Bar d{c, c, c};
确实,无法像往常一样构造初始化列表。
最终结论
这没有什么神秘之处。
你想构造一个 "list" 三对象。编译器必须构造那些从 a
复制的对象。