2012-11-22 19 views
7

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

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

std :: stringをconst参照constに渡します。その値は関数内で変更されていないためです。

Get関数では、実際に私はここで混乱しています。 std :: stringを値として返す方が意味があります。しかし、私はconst参照として文字列を渡すことによって、それが何か利点を確認していません。ストリングを参照としてリトラクトすると、エクスムーション速度が向上すると思いますが、わかりません。しかし、それを 'const'として返すと、これにはどんなメリットがありますか?

答えて

10

参照渡しや参照参照の速度の差はありません。どちらも元のオブジェクトへの参照を返すだけであり、コピーは含まれません。

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

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

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

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

要約すると、mStringを非公開にする方法があります。 Get()は、あなたが常にどのように文字列を格納しているかに応じて、値またはconst参照によって返すことができます。クラスは次のようになります。

class sample 
{ 
    std::string mString; 

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

"このコードでは、Get()がconst参照の代わりに値によって返されるように変更されていると、もちろんぶら下がりポインタが生成されます。 - いいえ、コンパイルを中止します( "一時的なアドレスを取ることはできません")。コンパイルするよりもUBを使う方が良いです。実際には拡張でコンパイルできますが、これは一般的な拡張機能ではなく、標準ではまだ診断を求めているため、ユーザーには少なくとも警告する必要があります。 –

+0

@SteveJessopありがとう、私は答えを修正しました。 – Angew

0

参考としてお返しください。コピーが必要な場合は、確かにそのリファレンスから作成することができます。

+0

「const」として返すのはどうでしょうか? –

+0

文字列を 'Set'メソッドでのみ変更したい場合は、' Get'を 'const std :: string&Get()const {return mString; } ' – chill

13

コンテナのいくつかの並べ替えから非自明なオブジェクトを返す方法を決定する問題は、実際に非自明である:

  • あなたが値を返す、そこからクラスが上の制約の任意の並べ替えを課した場合オブジェクトの場合は、const参照を返すことはできません。なぜなら、その不変量を強制する可能性を失うからです。明らかに、非const参照によってオブジェクトを返すことは、オブジェクトがそのメンバ関数が呼び出された場合にのみ有効です。const
  • オブジェクトへの参照を公開すると、不変量の問題を回避できますが、対応する型のオブジェクトが実際に実装の詳細として内部的に保持されていることを示しています。
  • オブジェクトを値で返すと、オブジェクトのコピーに大きなコストがかかります。

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

基本的には、理想的な選択肢はありません。疑わしいときには、オブジェクトがコピーするのに高価であることが知られている場合を除き、私は値段で返します。この場合、返信const&が返されます。

+1

はい。私はこれが古い質問だと知っていますが、とりわけインタフェースの場合、実装上の制限をかけたくない場合は、値の返り方がほとんど優れています。 –

+0

代わりにunique_ptrを返すことを検討しますか? –

0

ここに行うための最も一般的な事は、あなたが必要に応じて参照を使用するか、値をコピーすることができ、constの参照として値を返すために、次のようになります。

あなたが本当に 文字列のコピーを返すようにが必要な場合は
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 
関連する問題