16

std::string を const 参照として返すことに疑問があります。

class sample
{
public:
  std::string mString;
  void Set(const std::string& s)
  {
    mString = s;
  }
  std::string Get()
  {
    return mString;
  }
 };

Set 関数では、 std::string を const 参照として渡しています。 const の値は関数内で変化しないためです。

Get 関数では、実はここで混乱しています。値がより理にかなっているため、std::string を返します。しかし、文字列を const 参照として渡すことで利点が得られるかどうかはわかりません。文字列を参照として返すことで実行速度が上がるのではないかと思いますが、よくわかりません。しかし、それを「const」として返すと、これに何かメリットがありますか?

4

4 に答える 4

15

ある種のコンテナから自明でないオブジェクトを返す方法を決定する問題は、実際には自明ではありません。

  • 値を返すクラスがオブジェクトに何らかの制約を課す場合、非const参照を返すことはできません。これは、不変条件を強制する可能性が失われるためです。明らかに、非const参照によってオブジェクトを返すことは、メンバー関数が呼び出されたオブジェクトも非 である場合にのみ実行可能ですconst
  • オブジェクトへの参照を公開するconstと、不変条件の問題を回避できますが、対応する型のオブジェクトが実際には実装の詳細として内部に保持されていることを意味します。
  • オブジェクトを値で返すと、オブジェクトをコピーするためにかなりのコストがかかる場合があります。

クラスがさらに実行可能なモニターである場合は、値でオブジェクトを返す必要があります。そうしないと、呼び出し元がコピーする前にオブジェクトが変更される可能性があるためです。

基本的に、どの選択肢も理想的ではありません。疑わしい場合は、オブジェクトのコピーにコストがかかることがわかっている場合を除き、値で返しますconst&

于 2012-11-22T07:42:36.773 に答える
13

参照または const 参照による戻りに​​は速度の違いはありません。元のオブジェクトへの参照を返すだけであり、コピーは含まれないため、どちらも非常に高速です。

(非定数) 参照によって返されたオブジェクトは、その参照を通じて変更できます。あなたの特定の例でmStringは、公開されているため、とにかく(そして直接)変更できます。ただし、ゲッターとセッターを使用する通常のアプローチ (およびそれらを導入した主な理由) はカプセル化です。ゲッター/セッターを介したデータ メンバーへのアクセスのみを許可するため、設定されている無効な値を検出し、値の変更に応答し、一般に、クラスの実装の詳細をその中に隠しておきます。したがって、ゲッターは通常、const 参照または値によって戻ります。

ただし、const 参照によって戻る場合は、参照をバックアップするためにクラス内にのインスタンスを常に保持するようにバインドされます。std::stringつまり、後でクラスを再設計して、文字列を内部に格納するのではなく、getter でオンザフライで計算するようにしたい場合でも、それはできません。同時にパブリック インターフェイスを変更する必要があり、クラスを使用してコードを壊す可能性があります。たとえば、const-reference によって返される限り、これは完全に有効なコードです。

const std::string *result = &aSample.Get();

もちろん、このコードは、const 参照ではなく値で返すように変更された場合、コンパイルされないダングリング ポインターを生成します。 (訂正してくれた Steve Jessop に感謝)Get()

要約すると、私が取るアプローチはmString非公開にすることです。Get()常に文字列が格納されているかどうかに応じて、値または const 参照によって返すことができます。クラスは次のようになります。

class sample
{
  std::string mString;

public:
  void Set(const std::string &s)
  {
    mString = s;
  }
  std::string Get() const
  {
    return mString;
  }
};
于 2012-11-22T07:44:01.917 に答える
7

ここで行う最も一般的なことは、値を const-reference として返すことです。その後、必要に応じて参照を使用するか、値をコピーできます。

const std::string& Get() const
{
    return mString;
}

sample mySample;
const std::string &refString = mySample.Get(); // Const-reference to your mString
const std::string copyString = mySample.Get(); // Copy of your mString

本当に文字列のコピーを返す必要がある場合は、「 The Most Important Const」を利用して文字列の戻り値をコピーしないようにすることができます。

sample mySample;
const std::string &myString = mySample.Get();
// myString is now valid until it falls out of scope, even though it points to a "temporary" variable
于 2012-11-22T10:28:13.647 に答える
0

参考までに返します。コピーが必要な場合は、その参照から確実に作成できます。

于 2012-11-22T07:29:58.970 に答える