簡體   English   中英

const成員函數的語義是什么?

[英]What are the semantics of a const member function?

我知道該函數不允許更改對象的狀態,但是我想我讀過某個地方,允許編譯器假定如果函數使用相同的參數調用,它將返回相同的值,因此可以重用緩存的值(如果有)。 例如

class object
{
    int get_value(int n) const
    {
        ...
    }

...


object x;

int a = x.get_value(1);
    ...
int b = x.get_value(1);

然后編譯器可以優化第二次調用,並使用寄存器中的值或簡單地執行b = a;

這是真的?

const與程序語義有關,與實現細節無關。 當成員函數const不會更改對象的可見狀態時,應對其進行標記,並且應可在本身為const的對象上調用它。 在一個const上的類的成員函數X的類型, thisX const * :指針常數X對象。 因此,所有成員變量在該成員函數中都是有效的constmutable變量除外)。 如果您有const對象,則只能在其上調用const成員函數。

您可以使用mutable來指示成員變量即使在const成員函數中也可能更改。 這通常用於標識用於緩存結果的變量,或用於不影響實際可觀察​​狀態的變量,例如互斥鎖(您仍然需要將互斥鎖鎖定在const成員函數中)或使用計數器。

class X
{
    int data;
    mutable boost::mutex m;
public:
    void set_data(int i)
    {
        boost::lock_guard<boost::mutex> lk(m);
        data=i;
    }
    int get_data() const // we want to be able to get the data on a const object
    {
        boost::lock_guard<boost::mutex> lk(m); // this requires m to be non-const
        return data;
    }
};

如果通過指針保存數據,而不是直接(包括智能指針,如std::auto_ptrboost::shared_ptr ),然后將鼠標指針變成constconst成員函數,而不是指向的數據,這樣你就可以修改指向數據。

至於緩存:通常,編譯器無法執行此操作,因為狀態可能在兩次調用之間改變(尤其是在我使用互斥鎖的多線程示例中)。 但是,如果定義是內聯的,則編譯器可以將代碼提取到調用函數中,並優化在該函數中可以看到的內容。 這可能導致該功能僅被有效調用一次。

下一版本的C ++標准(C ++ 0x)將具有新的關鍵字constexpr 標記為constexpr函數返回常數,因此可以將結果緩存。 在此函數中可以執行的操作受到限制(以便編譯器可以驗證這一事實)。

沒有。

const方法是一種不會更改對象狀態(即其字段)的方法,但是您不能假設給定相同的輸入,就可以確定const方法的返回值。 換句話說, const關鍵字並不意味着該函數是一對一的。 例如,返回當前時間的方法是const方法,但是其返回值在兩次調用之間改變。

成員變量上的關鍵字mutable允許const函數更改當前對象的狀態。

不,它不會緩存數據(至少不是所有調用),因為以下代碼是有效的const函數,會隨着時間而變化:

int something() const { return m_pSomeObject->NextValue(); }

請注意,盡管指向的對象不是const,但指針可以是const,因此對SomeObject的NextValue的調用可能會或可能不會更改其自身的內部狀態。 這使函數每次被調用時都會返回不同的值。

但是,我無法回答編譯器如何使用const方法。 我聽說它可以優化某些功能,盡管我必須先確定一下。

成員函數上的const關鍵字將此參數標記為常量。 該函數仍然可以靜音全局數據(因此無法緩存),但不能靜音對象數據(允許調用const對象)。

在這種情況下, const成員函數意味着也this其視為const指針。 實際上,這意味着你不能修改的狀態this一個內部const成員函數。

對於沒有副作用的功能(即,您要實現的功能),GCC具有一個稱為“功能屬性”的pure函數(您可以通過說__attribute__((pure))使用它): http://gcc.gnu。 org / onlinedocs / gcc / Function-Attributes.html

還允許使用const方法修改靜態本地。 例如,以下代碼是完全合法的(重復調用bar()將返回遞增的值-而不是緩存的0):

class Foo
{
public:
    int bar() const
    {
        static int x = 0;
        return x++;
    }
};

我對此表示懷疑,該函數是否仍可以調用一個全局函數,該函數更改了世界的狀態並且沒有違反const。

除了成員函數可以修改全局數據這一事實之外,成員函數還可以修改所討論對象的顯式聲明的可變成員。

Corey是正確的,但請記住, 可以在const成員函數中修改任何標記為可變的成員變量。

這也意味着可以從其他const函數或通過其他const引用調用這些函數。


編輯:該死,被9秒毆打。 :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM