web-dev-qa-db-ja.com

const参照としてstd :: stringを返します

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

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

Set関数では、std :: stringをconst参照として渡します。これは、関数内で値が変更されていないためです。

そして、Get関数では、実際にはここで混乱しています。値がより意味のあるものとしてstd :: stringを返します。しかし、文字列をconst参照として渡すことで、何らかの利点が得られるかどうかはわかりません。文字列を参照として戻すことで、実行速度が上がると思いますが、よくわかりません。しかし、それを 'constとして返すことは、これに何らかの利益をもたらしますか?

11

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

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

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

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

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

要約すると、私が取るアプローチはmStringをプライベートにすることです。 Get()は、常に文字列が格納されることがどれだけ確実かによって、値またはconst-referenceで返すことができます。その場合、クラスは次のようになります。

_class sample
{
  std::string mString;

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

ある種のコンテナから重要なオブジェクトを返す方法を決定する問題は、実際には重要です。

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

クラスがさらに実行可能である場合 monitor オブジェクトを値で返す必要があります。そうしないと、オブジェクトが以前に変更される可能性があるためです。発信者はそれをコピーする機会がありました。

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

15
Dietmar Kühl

ここで行う最も一般的なことは、値を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

文字列のコピーを本当に必要する場合は、 " 最も重要な定数)を使用して文字列の戻り値のコピーを回避できます。 ":

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
6
Mark Ingram

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

0
chill