【问题标题】:Returning temporaries of type with deleted move/copy ctor使用已删除的移动/复制 ctor 返回类型的临时对象
【发布时间】:2016-01-27 15:35:10
【问题描述】:

考虑以下程序:

#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
}

示例会话:

$ 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。可能会或可能不会执行复制省略,但移动或复制 ctor(两者都在此处删除)必须仍然可以访问,如标准 (12.8/32) 所规定的那样。

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

【问题讨论】:

    标签: c++ temporary copy-elision


    【解决方案1】:

    这是标准行为。

    N4140 [stmt.return]/2: [...] 带有花括号初始化列表的 return 语句初始化对象 或通过指定初始化程序的复制列表初始化(8.5.4)从函数返回的引用 列表。 [...]

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

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

    【讨论】:

      【解决方案2】:

      [stmt.return]/2 ...带有非void类型表达式的return语句只能在返回值的函数中使用;表达式的值返回给函数的调用者。表达式的值被隐式转换为它出现的函数的返回类型。 return 语句可能涉及临时对象 (12.2) 的构造和复制或移动...带有 braced-init-list 的 return 语句通过以下方式初始化要从函数返回的对象或引用从指定的初始化列表中复制列表初始化(8.5.4)。

      [class.temporary]/1 类类型的临时对象在各种上下文中创建:...返回纯右值 (6.6.3) ...

      所以是的,据我所知,存在语义差异。 typedBrace 计算一个表达式S{},它产生一个S 类型的纯右值,然后尝试从该表达式复制构造它的返回值。 nakedBrace 直接从braced-init-list 构造它的返回值。

      这与S s{};(有效)与S s = S{};(无效)的情况相同,只是被某种程度的间接所掩盖。

      【讨论】:

        猜你喜欢
        • 2018-02-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-10
        • 2016-06-19
        • 2015-11-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多