返回本地对象时,C ++ 11移动语义

时间:2016-05-04 06:16:25

标签: c++ c++11 move-semantics

我看到了一些类似的问题,但找不到我的问题的明确解释。以下是代码(可在此处找到:http://melpon.org/wandbox/permlink/nBiik8pMkpKCD3Jv):

#include <iostream>

class A {
  public:
  explicit A(int a)         {std::cout << "Main constructor" << std::endl;}
  A(const A& a)             {std::cout << "Copy constructor" << std::endl;}
  A& operator =(const A& a) {std::cout << "Copy assignment" << std::endl; return *this;}
  A(A&& a)                  {std::cout << "Move constructor" << std::endl;}
  A& operator =(A&& a)      {std::cout << "Move assignemnt" << std::endl; return *this;}
};

A getA(bool b)        {std::cout << "In getA" << std::endl; A a(0); return b ? a : A(1);}
A getA_Move(bool b)   {std::cout << "In getA_Move" << std::endl; A a(0); return std::move(b ? a : A(1));}

int main(void) {
    std::cout << "\nA a0(getA(true))" << std::endl;
    A a0(getA(true));
    std::cout << "\nA a1(getA(false))" << std::endl;
    A a1(getA(false));    
    std::cout << "\nA a2(getA(true))" << std::endl;
    A a2(getA_Move(true));
    std::cout << "\nA a3(getA(false))" << std::endl;
    A a3(getA_Move(false));    
}

据我所知:函数的返回是一个右值(因为与左值相反,它没有名称,因此无法重复使用)。 因此,当创建将函数的返回值作为参数的对象时,如果该参数是可移动的,则应该移动该参数。然而,这不是我能观察到的:

Start


A a0(getA(true))
Main constructor
In getA
Copy constructor  <- Why is not this a move ?

A a1(getA(false))
Main constructor
In getA
Main constructor

A a2(getA(true))
Main constructor
In getA_Move
Copy constructor <- I would have expected a move here as well
Move constructor

A a3(getA(false))
Main constructor
In getA_Move
Main constructor
Move constructor

0

Finish

谢谢@ T.C.我修改程序使用正常if,然后程序按预期工作。可以在此处找到结果:http://melpon.org/wandbox/permlink/6h0ODi1SHdUj4HvX

2 个答案:

答案 0 :(得分:6)

简而言之,这是因为foo ? lvalue-of-X : rvalue-of-X导致从所选操作数初始化的临时类型X - 如果选择了第二个,则为副本,如果选择第三个,则为移动。

然后,返回临时值 - 首先移入返回值,然后移入main中的变量。

“局部变量被视为rvalues in return”规则仅在直接返回所述局部变量时适用。

海湾合作委员会在这里的处理方式有点过时 - 即使用-fno-elide-constructors,它也不会从第三个操作数移开。使用clang,当第三个操作数被选中时,你会看到the triple move

答案 1 :(得分:0)

这是由copy elision编译器优化引起的。 “复制省略是唯一可以改变可观察副作用的优化形式