多くの場合、関数からローカルを返すときに、RVO (戻り値の最適化) が開始されます。ただし、明示的に使用std::move
すると、RVO が発生しない場合は少なくとも移動が強制されますが、可能な場合は RVO が引き続き適用されると思いました。しかし、そうではないようです。
#include "iostream"
class HeavyWeight
{
public:
HeavyWeight()
{
std::cout << "ctor" << std::endl;
}
HeavyWeight(const HeavyWeight& other)
{
std::cout << "copy" << std::endl;
}
HeavyWeight(HeavyWeight&& other)
{
std::cout << "move" << std::endl;
}
};
HeavyWeight MakeHeavy()
{
HeavyWeight heavy;
return heavy;
}
int main()
{
auto heavy = MakeHeavy();
return 0;
}
このコードを VC++11 と GCC 4.71、デバッグおよびリリース ( -O2
) 構成でテストしました。copy ctor が呼び出されることはありません。move ctor は、デバッグ構成で VC++11 によってのみ呼び出されます。実際、特にこれらのコンパイラではすべて問題ないように見えますが、私の知る限り、RVO はオプションです。
ただし、明示的に使用する場合move
:
HeavyWeight MakeHeavy()
{
HeavyWeight heavy;
return std::move(heavy);
}
move ctor は常に呼び出されます。したがって、それを「安全」にしようとすると、さらに悪化します。
私の質問は次のとおりです。
- なぜ
std::move
RVO を防ぐのですか? - 「最善を期待」してRVOに頼る方が良いのはいつですか?また、いつ明示的に使用する必要があります
std::move
か? または、言い換えると、RVO が適用されていない場合でも、コンパイラの最適化にその作業を行わせ、移動を強制するにはどうすればよいでしょうか?