c++ - 返回具有已删除移动/复制构造函数的临时类型

标签 c++ temporary copy-elision

考虑以下程序:

#include<iostream>
using namespace std;

struct S
{
    S() = default;
    S(const S& other) = delete;
    S(S&& other) = delete;
    int i;
};

S nakedBrace()
{
     return {}; // no S constructed here?
}

S typedBrace()
{
     return S{};
}

int main()
{
    // produce an observable effect.
    cout << nakedBrace().i << endl; // ok
    cout << typedBrace().i << endl; // error: deleted move ctor
}

示例 session :

$ g++ -Wall -std=c++14 -o no-copy-ctor no-copy-ctor.cpp
no-copy-ctor.cpp: In function 'S typedBrace()':
no-copy-ctor.cpp:19:12: error: use of deleted function 'S::S(S&&)'
   return S{};
            ^
no-copy-ctor.cpp:8:5: note: declared here
     S(S&& other) = delete;

令我惊讶的是 gcc 接受 nakedBrace()。我认为这两个函数在概念上是等价的:构造并返回一个临时的 S。可能会或可能不会执行复制省略,但移动或复制构造函数(均在此处删除)必须仍可访问,如标准 (12.8/32) 所规定的那样。

这是否意味着 nakedBrace() 永远不会构造 S?或者它确实如此,但直接在带有大括号初始化的返回值中,以便在概念上不需要复制移动/ctor?

最佳答案

这是标准行为。

N4140 [stmt.return]/2: [...] 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. [...]

这意味着 nakedBracetypedBrace 执行的初始化等同于:

S nakedBrace = {}; //calls default constructor
S typedBrace = S{}; //calls default, then copy constructor (likely elided)

关于c++ - 返回具有已删除移动/复制构造函数的临时类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35041577/

相关文章:

c++ - 什么是复制省略和返回值优化?

c++14 通过引用返回一个值以优化性能

c++ - 用于排序的多态STL比较函数(class cmp class, class cmp int)

c++ - 我想将对类型 T 的非常量左值引用绑定(bind)到类型 T 的临时变量

mysql - 固定使用位置;使用临时的;使用文件排序

c++ - 大括号初始化防止非常量使用临时

linux - 在 Ubuntu Linux 中使用 C/C++ 编程

c++ - QTGUI - 如何在主窗口上打印来自其他类的消息(QString)?

c++ - 有没有一种编程方式来估计我的 CPU 执行 fp 操作所花费的时间?

c++ - 返回不可复制常量值的函数的不直观 RVO?