相关疑难解决方法(0)

从函数返回unique_ptr

unique_ptr<T>不允许复制构造,而是支持移动语义.然而,我可以unique_ptr<T>从函数返回一个并将返回的值赋给变量.

#include <iostream>
#include <memory>

using namespace std;

unique_ptr<int> foo()
{
  unique_ptr<int> p( new int(10) );

  return p;                   // 1
  //return move( p );         // 2
}

int main()
{
  unique_ptr<int> p = foo();

  cout << *p << endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码按预期编译和工作.那么该行如何1不调用复制构造函数并导致编译器错误呢?如果我必须使用line 2而不是它有意义(使用line 2也可以,但我们不需要这样做).

我知道C++ 0x允许此异常,unique_ptr因为返回值是一个临时对象,一旦函数退出就会被销毁,从而保证返回指针的唯一性.我很好奇这是如何实现的,它是在编译器中特殊的,还是在语言规范中有一些其他条款可以利用?

c++ unique-ptr c++11

328
推荐指数
6
解决办法
14万
查看次数

从函数返回值时使用std :: move()以避免复制

考虑支持默认移动语义的类型T. 还要考虑以下功能:

T f() {
   T t;
   return t;
}

T o = f();
Run Code Online (Sandbox Code Playgroud)

在旧的C++ 03中,一些非最佳编译器可能会调用两次复制构造函数,一个用于"返回对象",另一个用于o.

在c ++ 11中,由于tinside f()是左值,那些编译器可能像以前一样调用复制构造函数,然后调用o的移动构造函数.

是否正确说明避免第一次"额外复制"的唯一方法是t在返回时移动?

T f() {
   T t;
   return std::move(t);
}
Run Code Online (Sandbox Code Playgroud)

c++

49
推荐指数
2
解决办法
1万
查看次数

如果从函数返回,是否也会移动局部变量的成员子对象?

C++ 11标准规定,如果满足复制省略的条件(§12.8/31),则实现应将returned局部左值变量和函数参数视为rvalue first(move),如果重载解析不成功,则详细,然后将其视为左值(副本).

§12.8 [class.copy] p32

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

这还包括成员子对象吗?我测试了以下代码段:

#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();
}
Run Code Online (Sandbox Code Playgroud)

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

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

c++ local-variables move-semantics c++11

7
推荐指数
1
解决办法
592
查看次数

标签 统计

c++ ×3

c++11 ×2

local-variables ×1

move-semantics ×1

unique-ptr ×1