2011-11-26 124 views
3

我認爲「常量正確性」的概念非常明確,但是當我和其他人談論這個概念時,似乎我們對它的含義有不同的想法。有些人說這是關於一個在儘可能多的地方有「const」註解的程序。其他人定義一個程序爲const-correct,當且僅當沒有違反使用常量註釋的常量時(即它是編譯器檢查你的屬性)。const-correctness的定義是什麼?

所以我想知道,它的這些功能是const正確性:

struct Person { 
    string getName1() const { return _name; } 
    string getName2() { return _name; } 
    string getName3() const { _name = "John"; return _name; } 
    string getName4() { _name = "John"; return _name; } 

    string _name; 
}; 

我在網上搜索了相關定義上,但不能真正找到明確的答案,我也有懷疑可能會出現citogenesis的情況。那麼任何人都可以爲定義提供任何堅實的引用?

+0

getName3不會編譯,所以跳過那個。 –

+0

[什麼是「const正確性」?](http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.1) – cpx

+0

http://stackoverflow.com/questions/228783/什麼是關於使用下劃線在交流標識符 – Flexo

回答

4

在我看來,「const正確性」是指:

是不打算修改

一切都應該被標記爲const

這意味着編譯器可以告訴你何時犯了一個錯誤。 (它也可能有在一定條件下的優化的影響,但是這更多的是間接的好處,並取決於很多其他因素)

有三種基本的地方,這是非常有用的:

  1. 會員功能可以標記爲const,如同你的例子。這意味着你對該函數內的成員變量的訪問就像變量本身是const一樣。 (這是你給的例子中,雖然getName3()將無法​​正常工作)

  2. 「免費」的變量,局部和成員變量本身也被標記const - 一旦初始化它們可能不會改變。實施例 - 局部變量:

    int f(int i) { 
        const int square = i*i; 
        // do something here that uses, but doesn't change square 
        return square; 
    } 
    

    或自由變量:

    extern const double PI; // set somewhere else but not changed. 
    

    或成員變量:

    class foo { 
        const int state; // can't be changed once constructed 
        foo(int s) : state(i) {} 
    }; 
    
  3. 函數的參數也可以被標記const,該定義可以匹配的非常規聲明依然如此:

    void f(int i); 
    void f(const int i) { 
        // the fact that i is const is an implementation detail of f here 
    } 
    

    作爲一個側面說明const正確性引用在某些情況下是必需的:

    void g(const std::string& s); 
    void f(std::string& s); 
    

    這兩個人能在更多的地方使用:

    g("hi"); // Fine 
    f("hi"); // Not fine - you can't bind a temporary to a reference 
    

    當然,如果你意味着到改變s,然後通過一個臨時進入無論如何沒有多大意義。

0

This faq chapter只談論關於C++的const正確性。引用它:

這意味着使用關鍵字const來防止const對象變得 變異。

關於你的成員函數:

string getName1() const { return _name; } 

這一個常量,正確的。它只是返回一個成員變量的副本。

string getName2() { return _name; } 

這一個不是const正確的,因爲它沒有被聲明爲const成員。

string getName3() const { _name = "John"; return _name; } 

不是const正確的,因爲它修改了const成員函數中的成員變量。它應該會產生編譯錯誤。

string getName4() { _name = "John"; return _name; } 

它是常量正確的,因爲它修改了一個成員變量。從parashift

4

文字:

這意味着使用const關鍵字來防止獲得 突變const對象。

0

Const正確性正確地標識並指定方法可變或不可變的情況。

任何不可變的都應該標記爲const。

瞭解更多關於wikipedia

1

只有getName3違反常量,正確性,因爲_name是恆定的(具體而言,它是const std::string &)函數體中,並std::string::operator=const

getName2是設計不良,因爲它需要即使它不執行任何突變一個可變的情況下,所以應該宣佈const,因爲它本來導致意外的限制,即你不能把它通過const Person &

您也可以在混合中添加「易失性」和「右值」正確性,這些精確性相似。

通過其非局部效應可以感受到正確性。典型示例是關係運算符(operator<operator==):如果您未將它們標記爲const,許多標準算法和容器將不能與您的類一起使用,因爲它們通常會將運算符應用於常量元素引用。從這個意義上說,不是「儘可能的常量」對使用你的代碼提出了不必要的限制。從相反的觀點來看,如果你自己的函數不必要地需要引用一個對象,這同樣適用,因爲這樣可以避免你不必要地使用常量引用並且剝奪編譯時檢查你認爲的操作是不可變的確實沒有改變對象。

0

getName3()不正確,因爲它更改了名稱。其他人是正確的。

指定一個方法常數有時是需要的,有時需要。編寫完項目後,我會檢查哪些方法可以保持不變以提高代碼的可讀性。雖然仍然是編碼,但我沒有詳細說明方法,因爲它妨礙了工作的進展。出於同樣的原因,我宣佈所有成員都是公開的,直到我完成編碼,然後在適用的情況下申請專有和受保護。