返回临时类型,删除移动/复制ctor [英] Returning temporaries of type with deleted move/copy ctor

查看:153
本文介绍了返回临时类型,删除移动/复制ctor的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下程序:

#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)所要求的。

It astonishes me that gcc accepts nakedBrace(). I thought that conceptually the two functions are equivalent: A temporary S is constructed and returned. Copy elision may or may not be performed, but the move or copy ctor (both are deleted here) must still be accessible, as mandated by the standard (12.8/32).

这是否意味着 nakedBrace()从不构造S?或者它,但直接在返回值与大括号初始化,所以没有复制move / ctor在概念上需要?

Does that mean that nakedBrace() never constructs an S? Or it does, but directly in the return value with brace-initialization, so that no copy move/ctor is conceptually required?

推荐答案

这是标准的行为。


N4140 [stmt.return] / 2: [...]带有braced-init-list的return语句初始化对象
或引用从函数通过copy-list-initialization(8.5.4)从指定的初始化器
列表中返回。 [...]

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. [...]

这意味着 nakedBrace typedBrace 等效于以下内容:

This means that the initializations carried out by nakedBrace and typedBrace are equivalent to these:

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

这篇关于返回临时类型,删除移动/复制ctor的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆