私の理解では、C ++ 11では、関数からローカル変数を値で返す場合、コンパイラーはその変数をr値参照として扱い、それを関数から「移動」して返すことができます(もちろん、RVO / NRVOは代わりに発生しません)。
私の質問は、これは既存のコードを壊すことができないのですか?
次のコードを検討してください。
#include <iostream>
#include <string>
struct bar
{
bar(const std::string& str) : _str(str) {}
bar(const bar&) = delete;
bar(bar&& other) : _str(std::move(other._str)) {other._str = "Stolen";}
void print() {std::cout << _str << std::endl;}
std::string _str;
};
struct foo
{
foo(bar& b) : _b(b) {}
~foo() {_b.print();}
bar& _b;
};
bar foobar()
{
bar b("Hello, World!");
foo f(b);
return std::move(b);
}
int main()
{
foobar();
return EXIT_SUCCESS;
}
ローカルオブジェクトのデストラクタが暗黙的に移動されたオブジェクトを参照する可能性があるため、予期せず「空の」オブジェクトが表示される可能性があると考えていました。私はこれをテストしようとしましたが(http://ideone.com/ZURoeTを参照)、で明示的std::move
にせずに「正しい」結果を得ましたfoobar()
。これはNRVOが原因だったと思いますが、コードを再配置して無効にすることはしませんでした。
この変換(関数からの移動を引き起こす)は暗黙的に発生し、既存のコードを壊す可能性があるという点で私は正しいのですか?
更新 これは私が話していることを説明する例です。次の2つのリンクは同じコード用です。 http://ideone.com/4GFIRu-C ++ 03 http://ideone.com/FcL2Xj-C ++ 11
出力を見ると異なります。
それで、この質問は今になると思いますが、これは標準に暗黙の移動を追加するときに考慮されましたか?この種類のコードは十分にまれなので、この重大な変更を追加しても問題ないと判断されましたか?また、このような場合にコンパイラが警告するかどうかも疑問に思います...