多くの場合、関数からローカルを返すときにRVOが起動します。しかし、std::move
を明示的に使用するとRVOが発生しない場合でもRVOは可能な限り適用されます。しかし、そうではないようです。なぜstd :: moveは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
)設定でこのコードをテストしました。コピーctorは決して呼び出されません。 move ctorは、デバッグ設定でVC++ 11によってのみ呼び出されます。実際、これらのコンパイラではすべてがうまくいくようですが、私の知る限り、RVOはオプションです。
しかし、私は明示的にmove
を使用する場合:
HeavyWeight MakeHeavy()
{
HeavyWeight heavy;
return std::move(heavy);
}
移動CTORが常に呼び出されます。だから、それを "安全"にしようとすると悪化します。
私の質問は次のとおりです:
- なぜstd::move
はRVOを防止しますか?
- 「ベストを願って」RVOに頼る方が良いのはいつですか。また、いつ明示的にstd::move
を使うべきですか?つまり、RVOが適用されていない場合、どのようにしてコンパイラの最適化がその作業を行い、依然として実行を許可することができますか?
最近、なぜ人々は「最善の希望」について話しているのですか?どのような種類のコンパイラを使用しているのですか?C++ 11のサポートはありますが、RVOは正しくできませんか? –
コピーエリジョン(RVOの背後にあるメカニズム)は、特定の厳しい条件の下でのみ許可されます。 'std :: move'を書くことは、それらの条件が満たされないようにします。 –
@KerrekSBそしてこれらの条件はstd :: moveによって防止されています...? – cdoubleplusgood