2012-11-22 57 views
7

我有疑問返回std :: string作爲const引用。返回std ::字符串作爲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,因爲它的值在函數內部沒有改變。

而在獲取函數,其實我很困惑這裏。返回std :: string作爲值更有意義。但我不確定,通過傳遞字符串作爲const引用有什麼好處。通過迴避字符串作爲參考會增加執行速度,我認爲所以,但我不確定。但是將它返回爲const會爲此帶來什麼好處?

回答

10

通過引用或const引用返回沒有速度差 - 兩者都非常快,因爲它們只是返回對原始對象的引用,不涉及複製。

可以通過該引用修改(非const)引用返回的對象。在您的具體示例中,mString是公開的,因此無論如何(和直接)都可以進行修改。然而,getter和setter的常用方法(以及引入它的主要原因)是封裝 - 您只允許通過getter/setter訪問數據成員,以便您可以檢測設置的無效值,響應值更改以及只是通常保留隱藏在其中的類的實現細節。所以getters通常通過const引用或值來返回。

但是,如果您通過const引用返回,它會將您綁定到總是在您的類中保留std::string的實例以備份引用。也就是說,即使你以後想重新設計你的類,以便它在getter中動態地計算字符串,而不是在內部存儲它,你也不能。您必須同時更改您的公共接口,這可能會使用該類破壞代碼。例如,只要你通過常量引用返回,這是完全合法的代碼:

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引用將避免不變量的問題,但仍意味着相應類型的對象實際上在內部保存爲實現細節。
  • 通過值返回對象可能會導致複製對象的重大成本。

如果類是進一步您一定要通過值返回對象,否則該對象可以調用方有任何機會複製之前突變可行monitor

基本上,沒有任何選擇是理想的。如果有疑問,我會根據價值回報,除非已知該複製品價格昂貴,在這種情況下,我可能會使用返回const&

+1

是的。我知道這是一個古老的問題,但特別是在接口的情況下,其中一個不想對實現構成限制,通過返回值更好。 –

+0

你會考慮返回一個unique_ptr嗎? –

0

在這裏做的是返回值作爲常量引用,那麼你可以使用一個參考或複製必要的值中最常見的事情:

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 
相關問題