如果从函数返回,局部变量的成员子对象是否也会被移动? [英] Will member subobjects of local variables be moved too if returned from a function?

查看:143
本文介绍了如果从函数返回,局部变量的成员子对象是否也会被移动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C ++ 11标准规定,如果满足复制精度的条件(§12.8/ 31 ),实现将处理 return ed local lvalue变量和函数参数,作为右值第一个(move),如果重载解析不成功,则应将其视为左值(副本)。

The C++11 standard states that, if the conditions for copy elision are met (§12.8/31), the implementation shall treat a returned local lvalue variable and function parameters, as an rvalue first (move), and if overload resolution doesn't succeed as detailed, shall then treat it as an lvalue (copy).

§12.8[class.copy] p32


当满足复制操作的删除标准时,除非源对象是函数参数,并且要复制的对象由lvalue指定,否则将满足复制操作的标准,重载分辨率选择复制的构造函数首先执行,就像对象是由右值指定的。如果重载分辨率失败,或者如果所选构造函数的第一个参数的类型不是对象类型(可能是cv限定的)的右值引用,则会再次执行重载分辨率,将对象视为左值。 [注意:无论是否发生复印偏差,都必须执行此两阶段重载分辨率。如果不执行elision,则它确定要调用的构造函数,并且即使调用被省略,所选构造函数也必须可访问。 -end note ]

When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. If overload resolution fails, or if the type of the first parameter of the selected constructor is not an rvalue reference to the object’s type (possibly cv-qualified), overload resolution is performed again, considering the object as an lvalue. [ Note: This two-stage overload resolution must be performed regardless of whether copy elision will occur. It determines the constructor to be called if elision is not performed, and the selected constructor must be accessible even if the call is elided. —end note ]

这是否还包括成员子对象?我使用以下代码段测试:

Does this also include member subobjects? I tested with the following snippet:

#include <iostream>

struct traced{
  traced(){ std::cout << "default ctor\n"; }
  traced(traced const&){ std::cout << "copy ctor\n"; }
  traced(traced&&){ std::cout << "move ctor\n"; }
};

struct X{
  traced t;
};

traced f(){
  X x;
  return x.t;
}

int main(){
  traced t = f();
}


并且GCC 4.7 ToT和Clang 3.1 ToT都不会显示move ctor,这使我相信标准不包括成员子对象。

Live example on Ideone. And neither GCC 4.7 ToT nor Clang 3.1 ToT will display "move ctor", which leads me to believe that the standard doesn't include member subobjects.

我忽略了什么吗?我的测试代码坏了吗?

Did I overlook something? Is my test code broken? What exactly causes the output to be as it is?

推荐答案

当返回子对象时,你不能删除它的构造。以这种方式考虑:移动和复制elision基本上等于在最终被移动或复制到的地方构造对象。这对完整的对象工作,因为将有适当的空间被搁置。它不适用于子对象,因为您将构造包围对象。即使这与子对象具有相同的大小,即有足够的空间,包围的对象被销毁,并可能对子对象做有趣的事情。

When returning a subobject you can't elide its construction. Think of it this way: move and copy elision essentially amount to constructing the object in the place it would eventually be moved or copied to. This works for complete objects because there will be the appropriate space be set aside. It doesn't work with subobjects because you would construct the enclosing object. Even if this has the same size as the subobject, i.e. there is enough space, the enclosing object gets destroyed and may do funny things to the subobjects.

有效地,这意味着该主体的建构不能被省略。

Effectively, this means that construction of the subject cannot be elided.

这篇关于如果从函数返回,局部变量的成员子对象是否也会被移动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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