我理解当对象从函数按值返回时,它们的复制构造函数被调用。如果一个类有一个删除的复制构造函数,按值返回将失败。
struct X {
X(const X &) = delete;
};
X f() {
return X{};
}
error: call to deleted constructor of 'X'
C++11 为我们提供了扩展初始化器。我在 SO 帖子的某处读到这个
X f() {
return {};
}
与
相同X f() {
return X{};
}
那么为什么下面的代码没有报错呢?它通过了,我什至可以调用 main 中的函数:
struct D {
D(const D &) = delete;
};
D f() { return {}; }
int main()
{
f();
}
Here is a demo.没有报错。我觉得这很奇怪,因为我认为应该调用复制构造函数。谁能解释为什么没有报错?
最佳答案
And I read somewhere on a SO post that this [...] is the same as [...]
他们错了。它们相似,但不相同。
通过使用花括号初始化列表,您可以就地 初始化返回值。如果您创建临时文件,那么您所做的就是创建临时文件,然后将其复制到返回值中。任何称职的编译器都会忽略它,但复制构造函数仍然必须是可访问的。
但是由于 braced-init-list 就地初始化返回值,您不需要访问复制构造函数。
来自标准第 6.6.3 节,p2:
A return statement with a braced-init-list initializes the object or reference to be returned from the function by copy-list-initialization (8.5.4) from the specified initializer list.
请注意,“copy-list-initialization”与“copy-initialization”不同;它不进行任何复制,因此不需要可访问的复制构造函数。 “copy-list-initialization”和“direct-list-initialization”之间的唯一区别是前者会阻塞 explicit
构造函数。
关于c++ - 为什么在按值返回列表初始化对象时不调用复制构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15328244/