c++ - 为什么在按值返回列表初始化对象时不调用复制构造函数?

标签 c++ c++11

我理解当对象从函数按值返回时,它们的复制构造函数被调用。如果一个类有一个删除的复制构造函数,按值返回将失败。

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/

相关文章:

c++ - 获取 vector 中的特定元素

c++ - 如何用C++控制TabTip键盘的显示和关闭

线程的 C++11 vector 参数似乎未初始化

c++ - 完美转发一个参数包: convert args without expansion?

c++ - 右值引用的生命周期

C++段错误问题

c++ - 如何正确推断模板的返回类型?

c++ - 代码中奇怪的 constexpr 参数

c++ - c++ `override`/`final` 说明符的反义词是什么?

c++ - cpp 程序中的意外输出