在过去的一天左右,我一直在学习移动构造函数,试图坚持按照大多数人似乎建议的价值返回的一般规则,并且遇到了一个有趣的(对我而言)困境.
假设我有一个昂贵的构造/复制类'C',它具有正确定义的复制构造函数,赋值运算符,移动构造函数和移动赋值运算符.
首先,这段代码省略了我预期的复制构造函数:
C make_c1() {
return C();
}
Run Code Online (Sandbox Code Playgroud)
就像这样:
C make_c2() {
C tmp;
return tmp;
}
Run Code Online (Sandbox Code Playgroud)
这样做(无论我传入1还是2):
C make_c3(int a) {
return a == 1 ? make_c1() : make_c2();
}
Run Code Online (Sandbox Code Playgroud)
我遇到这个问题时,我遇到了一个问题:
C make_c4(int a) {
C tmp;
return a == 1 ? make_c1() : tmp;
}
Run Code Online (Sandbox Code Playgroud)
传入1会触发RVO以获取make_c1的结果,但传入2将触发tmp上的复制构造函数.
将函数修改为以下内容会导致为tmp触发移动构造函数:
C make_c5(int a) {
C tmp;
return a == 1 ? make_c1() : std::move(tmp);
}
Run Code Online (Sandbox Code Playgroud)
一切都非常精彩,除了......
在这些简单的例子中,RVO已被触发,就像我希望的那样.
但是,如果我的代码稍微复杂一些,并且某些编译器在最后一个函数中没有引起RVO呢?在这种情况下,我需要在std :: move中包含对make_c1的调用,这会使代码在那些唤起RVO的编译器上效率降低.
所以我的问题是:
我一直在玩的编译器是Cygwin上的GCC 4.5.3.