1

ローカル変数への参照を返すのが悪い考えであることは誰もが知っています。ただし、参照を返すことが本当に良い考えであるかどうか、いつそれを行うべきか、いつすべきでないかについての適切なルールを決定できるかどうかは疑問です。

参照を返すことに関する私の問題は、呼び出し元の関数が、責任を負うべきではないオブジェクトの寿命を気にする必要があることです。不自然な例として:

#include <vector>

const int& foo() {
  std::vector<int> v = {1, 2, 3, 4, 5};
  return v[0];
}

int main(int argc, const char* argv[])
{
  const int& not_valid = foo();
  return 0;
}

ここで、 はvectorの最後で範囲外になり、fooその内容を破棄し、その要素への参照を無効にします。vector::operator[]は要素への参照を返すため、この参照が からさらに返されるとfoo、 の参照mainがぶら下がっています。const 参照は一時的なものへの参照ではないため、ここでの寿命が延びるとは思いません。

私が言ったように、これは不自然な例であり、おそらく の作者は、参照としてfoo返そうとするほど愚かではないでしょうv[0]. ただし、参照を返すために、呼び出し元が所有していないオブジェクトの有効期間を気にする必要があることは簡単にわかります。要素を にプッシュすると、要素がvectorコピーされるため、vectorが責任を負います。参照引数を渡す場合、この問題は存在しません。これは、呼び出し元が続行してオブジェクトを破棄する前に関数が完了することがわかっているためです。

参照を返すと、次のような素敵な配列のような構文が可能になることがわかりますが、次v[0] = 5のようなメンバー関数を持つことの何が悪いのv.set(index, value)でしょうか? 少なくともこれで、内部オブジェクトを公開することはありません。参照を返すことによってもパフォーマンスが向上する可能性があることはわかっていますが、RVO、 Named RVO (NRVO) 、および move セマンティクスを使用すると、無視できるか存在しません。

そのため、参照を返すことが本当に安全な状況を想像しようとしましたが、関連する可能性のある所有権セマンティクスのさまざまな順列をすべて理解することはできません。いつこれを行うべきかについて、適切なルールはありますか?

注: s の所有権を処理するより良い方法vectorはスマート ポインターを使用することですが、別のオブジェクトで同じ問題が発生します。スマート ポインターの所有者は誰ですか?

4

2 に答える 2

10

参照を返すには、たくさんの良い使い方があります。1つは、あなたが言ったように、ネイティブ逆参照演算子のようなものをエミュレートすることです:

struct Goo
{
    int & operator[](size_t i) { return arr[i]; }
    int & front()              { return arr[0]; }

    // etc.

private:
    int * arr;
};

別の使用例は、渡されたものへの参照を返す場合です。典型的な例は、次のような連鎖可能な操作です<<

std::ostream & operator<<(std::ostream & os, Goo const & g)
{ 
    return os << g[3];
}

最後の例として、スレッドセーフなグローバル オブジェクトを次に示します。

Goo & get_the_object()
{
    static Goo impl;
    return impl;
}

参照は言語の不可欠な部分であり、関数呼び出しによって返される可能性があります。あなたが言ったように、オブジェクトの寿命を理解することは重要ですが、それは常に真実であり、参照を返すという特定の問題ではありません。

于 2012-10-25T22:09:28.093 に答える
0

個人的には、Singleton パターンを実装したいときに静的変数への参照を返すのが好きです。

SomeClass& getTheSingleton()
{
    static SomeClass theInstance;
    return theInstance;
}

ポインターが初期化されるかどうかに関係するロジックを記述する必要はありません。これにより、静的初期化の順序をある程度制御できます。

于 2012-10-26T00:15:30.063 に答える