2010-10-14 72 views
5

const正確性讓我有些困惑。在C++中使用const的正確方法是什麼?

你用什麼經驗法則來決定何時應該是const或不是?

例如考慮這個例子

class MyClass 
{ 
    string ToString(); // this one? 
    const string& ToString(); // or this? 
    const string& ToString() const; // or this? 

    char* ToString(); // What about this? 
    const char* ToString(); // or this? 
    const char* ToString() const; // or this? 
    const char const* ToString(); // Is this legal? 
    const char const* ToString() const; // how about this? 
    char const* ToString(); // or even this? 
}; 

Const會變得非常混亂。

所有這些ToString方法之間有什麼區別?

如果我理解正確,第一個返回一個新的字符串對象,如果需要可以修改 。 第二個返回一個常量引用,也許它應該是字符串const & ToString()。 第三個可能是廢話,因爲引用總是不變的是正確的?

以爲我會拋出舊char *版本在那裏比較,因爲我有方法返回對象指針,我不知道它們是否應該是const或不。

我想我只是想了解const的正確性的限制和好處,以及如何確定某些東西是否應該是const,以及如何正確應用const,因爲將const放在不同的地方會改變含義。

編輯:另外,我該如何處理'...丟棄限定符'。這實際上意味着什麼?

+0

第二個和第三個之間沒有什麼區別。 – dan04 2010-10-14 23:51:31

+9

我寧願從一般規則開始,「如果你可以把const放在某個地方,那麼你應該。」很顯然,這個規則有很多例外(其中很多),但實際上,你可以使const變量越多,推斷,調試和維護代碼就越容易。我認爲這比起更常見的「讓我們只在必要的地方使用常量,並且可能在其他地方使用常常更好」。 – 2010-10-14 23:51:42

+0

您是否閱讀過Herb Sutter的GOTW文章[「Const Correctness?」](http://www.gotw.ca/gotw/006.htm)它通過一個示例類來解釋(1)應該是什麼'const' (2)使用'const'的效果是什麼。這絕對是一個很好的起點。 – 2010-10-15 00:02:50

回答

2

您使用const的位置取決於功能的用途。正如詹姆斯暗示在他的評論(這是值得投入作爲一個答案),把const任何地方,你可以:

如果該功能是爲了它的對象實例上修改狀態,const在年底簽名。

如果該功能旨在修改其參考或指針參數中的一個,請勿將放在參數const上。

如果引用的變量通過指針或引用應該被修改,const上的類型(記住,const適用於定義之前立即的一部分)。

如果返回的引用/指針引用的變量不應該被接收到,const上的類型。

如果不知道目的的功能,回答問題中給出的例子是不可能的。我傾向於使用string ToString() constchar* ToString() const,並且有關誰負責char*的文檔非常明確。


作爲一個額外的筆記,const char*char const*是相同的(指針不可修改的字符)。另一方面,char* const是不可修改的指向可修改字符的指針。

+0

你的wtf/min的貢獻是排序後[這裏](http://area51.stackexchange.com/proposals/11464/code-review?referrer=aWNm_PdciyFqjFW8CUacGw2「代碼審查」):) – greatwolf 2011-01-16 23:17:46

-1

我發現this是一個有益的指導,

+2

-1鏈接到C++ FQA Lite。 – 2010-10-14 23:53:19

-1

你用什麼憑經驗來決定何時東西應該是const或不?

在任何地方都可以使用它。然後,不要當你需要修改對象或授予訪問某些可能修改對象的內容(即將引用或代理返回到內部狀態)時使用它。

第三個可能是廢話,因爲引用總是不變的是正確的?

不,這是不正確的。引用是別名,而不是變量。因此,您無法更改引用「指向」哪個變量,就像您可以使用指針一樣。但是,您可能需要引用可變對象(std::string&)。

所有這些ToString方法有什麼區別?

他們都非常的內存管理技術有所不同,但在一個高的水平,他們都做同樣的事情,除了以下:

char* ToString(); 

該ONT返回一個指向可變字符數組(可能是內部狀態)。

注意的家人:

char const* ToString(); 
const char* ToString(); // or this? 
const char const* ToString(); // Is this legal? 

都寫同樣的事情不同的方式。無論您是否寫入,本機類型都是按值返回時的常量。

以下2在C++返回一個字符串的首選方式(末尾提供了一個額外的const):

string ToString(); // this one? 
const string& ToString(); // or this? 

這兩個您將使用的一個取決於你在哪裏得到的值。如果字符串是一個數據成員,我建議你去後者,因爲它通常比較快,但是如果你的字符串實現使用了寫時複製語義,那麼不會太多。如果您必須計算一個值並將其返回,則必須使用前者,因爲您無法返回對局部變量的引用。

下面兩個是正確的,但我還是建議你使用std::string

const char* ToString() const; // or this? 
const char const* ToString() const; // how about this? 
+0

'const char *'和'char const *'是可修改的p ointers不可修改的字符。 'char * const'是一個不可修改的指向可修改字符的指針。 'const'適用於它之前發生的任何事情,或者,如果它是第一個,它會立即發生。 – Zooba 2010-10-15 00:07:02

+0

括號後面的'const'不是多餘的:它適用於「* this」對象,而不是返回類型。 – aschepler 2010-10-15 00:07:28

+0

糟糕,在那個上有點太快了。我會編輯它。 – 2010-10-15 00:25:37

0

您不能重載具有相同名稱和相同參數但返回類型不同的函數。你可能知道,但只是確定。

const括號後的()表示該函數不會更改您調用的對象。通常稱爲ToString的東西不會更改對象,所以在所有情況下,您可能都需要一個const方法。

返回string和返回const string&之間的區別是,參考不作和對象複製並可能會更快,但你只能做它,如果你已經有了一個string對象(例如,作爲一個私有成員MyClass)。如果沒有(例如你需要將幾位數據拼接在一起,然後返回該字符串),則需要按值返回string

使用string對象通常優選使用C風格char*三分球,但既然你問:第四個,char*,就會讓其他代碼改變返回的字符串,這可能是一件壞事內的字符。 const char*char const*const char const*都是一樣的東西。 char *const在技術上是不同的,但它不會做太多的返回類型,因爲返回const int並不重要的原因:調用者可以複製然後更改返回值。

總之,最好的形式是,爲了:

const string& ToString() const; 
string ToString() const; 
const char* ToString() const; 
0

在這個問題的一些變化是在返回stringchar *。我認爲這與const討論無關(如果不是,請告訴我);我正在考慮string回報變化。

class MyClass 
{ 
    string ToString();    // A 
    string & ToString();   // B (I added this) 
    const string& ToString();  // C 
    const string& ToString() const; // D 
}; 

我的偏好順序如下:

  • 返回類型說明符[此:d,C,B,A。

    在所有的變型中,被const兩種方式使用D中的第一個const]

    這意味着返回的對象不能用於修改返回的對象。這句話聽起來很有趣,不是嗎?那麼,可能有其他方法來修改對象,而這const不能阻止。看到這個FAQ item

  • 類不變[在d第二const]

    這意味着該方法不發生變異(修改)類對象。

我比D更喜歡D,因爲D保證調用該方法的對象不會被修改。如果一個目標可以實現(即方法可以實現)而不需要修改一個目標,這在設計方面是一個巨大的勝利。我可以隨時使用它。 但是如果對象必須被修改(即沒有方法可以在不修改對象的情況下實現),則排除D.

其中,B和C都優於A,因爲B和C返回一個引用,它避免了A中所需的複製構造。

在B和C之間,C是可取的,因爲它返回const參考。

+1

但他們有不同的語義。從我的角度來看,唯一有意義的(在大多數情況下)是B和D.你也可以考慮'string ToString()const;'。 B只在你想讓用戶修改字符串時纔有用。如果您只是要返回對「MyClass」的字符串成員的引用,則首選D。如果字符串不是成員(即在函數調用期間計算),請使用上面的表格。 C的一個可能用途是如果MyClass必須計算字符串,但將其作爲成員變量緩存(因此不是const)。然而,那麼你應該使用'可變' – Gretchen 2010-10-15 06:37:57

+0

是的,我也會在幾乎所有情況下避免選項C.獨自一人是有道理的。定義_both_ B和D是有意義的,如果你想要版本B.如果字符串是在函數調用時計算的,而不是簡單的成員,那麼版本A是合理的。 – aschepler 2010-10-15 16:00:33

相關問題