Edited at

[短文メモ][C++11]関数内のローカル変数を返すのに右辺値参照は要らない

More than 3 years have passed since last update.


右辺値参照を使うと無駄なコピーを避けられるよ、と聞いたので


ダメなコード

#include <vector>

#include <iostream>

using std::cout; using std::endl;

std::vector<int> && test(){
std::vector<int> vec;
// vectorにいろいろ挿入する処理(この記事と関係ないので省略)
cout << 2 << endl;
return std::move(vec);
}

int main()
{
cout << 1 << endl;
std::vector<int> v = test();
cout << 3 << endl;
return 0;
}


2まで表示されて、Segmentation Faultで落ちる。

似たようなことでハマった人がいないか、Stack Overflowで探してみると、やっぱりいたので、回答を要約すると。


右辺値参照は、あくまでも参照の一種だ

関数を抜けだした時点でローカル変数は破棄されるので、ローカル変数の参照を返すのは、そもそも間違い。

右辺値参照だからとか、moveを使ったからとか、そんなのは関係ない。

古き良きC++時代の(左辺値)参照の場合と全く同じ理由で、ローカル変数の参照を返してはいけない。


どうせコンパイラが最適化してくれるよ

return-value-optimization (RVO)と言って、こういう場合は無駄なコピーが発生しないよう、コンパイラが最適化してくれる。

だから、いらんことをしなくていい。


結論:普通に値で返せ。


普通のやりかた

std::vector<int> /* &&は不要 */ test(){

std::vector<int> vec;
// vectorにいろいろ挿入する処理(この記事と関係ないので省略)
return vec; // std::move不要
}


参考文献(似たようなことでハマった人たち)

segmentation fault when moving std::vector [closed] - Stack Overflow

C++11 rvalues and move semantics confusion (return statement) - Stack Overflow