LoginSignup
22
14

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-04-27

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

ダメなコード
#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

22
14
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
14