7

§12.8/31C++11标准规定,如果满足复制省略的条件return(详细,然后将其视为左值(副本)。

§12.8 [class.copy] p32

当满足或将满足复制操作的省略标准时,除了源对象是函数参数的事实,并且要复制的对象由左值指定时,选择复制的构造函数的重载决策是首先执行好像对象是由 rvalue 指定的。如果重载决议失败,或者如果所选构造函数的第一个参数的类型不是对对象类型的右值引用(可能是 cv 限定的),则再次执行重载决议,将对象视为左值。[注:无论是否会发生复制删除,都必须执行此两阶段重载解决方案。它确定如果不执行省略则要调用的构造函数,并且即使调用被省略,所选构造函数也必须是可访问的。——尾注]

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

#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();
}

Ideone 上的实时示例。 GCC 4.7 ToT 和 Clang 3.1 ToT 都不会显示“move ctor”,这让我相信标准不包括成员子对象。

我忽略了什么吗?我的测试代码坏了吗?究竟是什么导致输出保持原样?

4

1 回答 1

6

返回子对象时,您不能省略其构造。可以这样想:移动和复制省略本质上相当于在最终将被移动或复制到的位置构建对象。这适用于完整的对象,因为将留出适当的空间。它不适用于子对象,因为您将构造封闭对象。即使它与子对象具有相同的大小,即有足够的空间,封闭对象也会被破坏并且可能对子对象做一些有趣的事情。

实际上,这意味着不能省略主题的构建。

于 2012-02-07T20:16:08.883 回答