我看到了一些类似的问题,但找不到我的问题的明确解释。以下是代码(可在此处找到: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
答案 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编译器优化引起的。 “复制省略是唯一可以改变可观察副作用的优化形式”