1. ホーム
  2. c++

[解決済み] C++ ローカル変数への参照を返す

2022-02-15 11:17:11

質問

以下のコード(func1())は、iを返さなければならないのであれば、正しいのでしょうか?ローカル変数への参照を返すと問題があるとどこかで読んだ覚えがあります。func2()とはどう違うのでしょうか?

int& func1()
{
    int i;
    i = 1;
    return i;
}

int* func2()
{
    int* p;
    p = new int;
    *p = 1;
    return p;
}

解決方法は?

このコードスニペットです。

int& func1()
{
    int i;
    i = 1;
    return i;
}

なぜなら、関数呼び出しのスコープに限定されたライフタイムを持つオブジェクトへのエイリアス (参照) を返しているからです。つまり、一度 func1() が返ります。 int i が死ぬと、関数から返された参照は存在しないオブジェクトを参照することになり、価値がなくなります。

int main()
{
    int& p = func1();
    /* p is garbage */
}

2番目のバージョンは、変数が関数呼び出しのライフタイムに縛られないフリーストアに割り当てられるので、動作します。しかし、あなたは delete を使用すると、割り当てられた int .

int* func2()
{
    int* p;
    p = new int;
    *p = 1;
    return p;
}

int main()
{
    int* p = func2();
    /* pointee still exists */
    delete p; // get rid of it
}

通常、ポインタをいくつかの RAII クラスやファクトリー関数を使うことで delete を自分で作る。

どちらの場合でも、値そのものを返せばいいのです(あなたの提供した例は、おそらく作為的なものだと思いますが)。

int func3()
{
    return 1;
}

int main()
{
    int v = func3();
    // do whatever you want with the returned value
}

大きなオブジェクトを同じ方法で返すのは全く問題ないことに注意してください。 func3() はプリミティブな値を返すので、現在ではほとんどのコンパイラが何らかの形で 戻り値の最適化 :

class big_object 
{ 
public:
    big_object(/* constructor arguments */);
    ~big_object();
    big_object(const big_object& rhs);
    big_object& operator=(const big_object& rhs);
    /* public methods */
private:
    /* data members */
};

big_object func4()
{
    return big_object(/* constructor arguments */);
}

int main()
{
     // no copy is actually made, if your compiler supports RVO
    big_object o = func4();    
}

興味深いことに、テンポラリにバインドすると コンスト 参照は 完全に合法な C++ .

int main()
{
    // This works! The returned temporary will last as long as the reference exists
    const big_object& o = func4();    
    // This does *not* work! It's not legal C++ because reference is not const.
    // big_object& o = func4();  
}