上下文:我正在进行实验,以了解gcc何时执行RVO,如果不执行,何时使用移动语义。我的gcc版本是g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
。
问题:我有一个按值返回Foo
的函数。编译器无法执行RVO,因为有两个可能的命名返回值。当我使用三元运算符选择要返回的Foo
时,则需要显式调用std::move
以避免复制。使用if语句时,不需要std::move
。为什么会有差异?
码:
#include <iostream>
using namespace std;
struct Foo {
std::string s;
Foo() { cout << "Foo()\n"; }
~Foo() { cout << "~Foo()\n"; }
Foo(const Foo& other) : s(other.s) { cout << "Foo(const Foo&)\n"; }
Foo(Foo&& other) noexcept : s(move(other.s)) { cout << "Foo(Foo&&)\n"; }
};
Foo makeFooIf(bool which) {
Foo foo1; foo1.s = "Hello, World1!";
Foo foo2; foo2.s = "Hello, World2!";
if (which) return foo1;
else return foo2;
}
Foo makeFooTernary(bool which) {
Foo foo1; foo1.s = "Hello, World1!";
Foo foo2; foo2.s = "Hello, World2!";
return which ? foo1 : foo2;
}
Foo makeFooTernaryMove(bool which) {
Foo foo1; foo1.s = "Hello, World1!";
Foo foo2; foo2.s = "Hello, World2!";
return which ? move(foo1) : move(foo2);
}
int main()
{
cout << "----- makeFooIf -----\n";
Foo fooIf = makeFooIf(true);
cout << fooIf.s << endl;
cout << "\n----- makeFooTernary -----\n";
Foo fooTernary = makeFooTernary(true);
cout << fooTernary.s << endl;
cout << "\n----- makeFooTernaryMove -----\n";
Foo fooTernaryMove = makeFooTernaryMove(true);
cout << fooTernaryMove.s << endl;
cout << "\n----- Cleanup -----\n";
return 0;
}
输出:
----- makeFooIf -----
Foo()
Foo()
Foo(Foo&&)
~Foo()
~Foo()
Hello, World1!
----- makeFooTernary -----
Foo()
Foo()
Foo(const Foo&)
~Foo()
~Foo()
Hello, World1!
----- makeFooTernaryMove -----
Foo()
Foo()
Foo(Foo&&)
~Foo()
~Foo()
Hello, World1!
----- Cleanup -----
~Foo()
~Foo()
~Foo()
最佳答案
在某些情况下会有一个隐含的举动:
§12.8.32
我的大胆
关于c++ - 使用if语句 move 构造函数,但使用三元运算符复制构造函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46107480/