1. 程式人生 > >const關鍵字對C++成員函數的修飾

const關鍵字對C++成員函數的修飾

基本類型 int 而不是 自定義變量 con 不想 靜態成員 原因 tab

const對C++成員函數的修飾分為三種:1. 修飾參數;2. 修飾返回值;3. 修飾this指針。簡述一下知識點如下,以後找功夫再完善。

1. 對函數參數的修飾。

  1)const只能用來修飾輸入參數。輸出型參數不能用const來修飾。

  2)如果輸入參數采用“指針傳遞”,那麽加const修飾可以防止意外地改動該指針,起到保護作用。

  3)如果輸入參數采用“值傳遞”,函數將產生臨時變量(局部變量),復制該參數的值並且壓入函數棧。函數中使用該參數時,訪問的是函數棧中臨時變量的值,原變量無需保護,所以不要加const修飾。

  4)基本變量類型的參數作為“值傳遞”的輸入參數,無需采用引用。自定義變量類型(class類型,struct類型)參數作為“值傳遞”的輸入參數,最好采用"const+引用"格式,即 void func(const A& a)。原因是自定義變量類型作為值傳遞時,設計創建臨時變量,構造,復制,析構,這些過程很消耗時間。

  從函數棧的基本原理考慮原因。我們知道,函數在被調用時,會為創建各個實參創建臨時變量並將其壓入函數棧。如果是基本變量類型,則壓入函數棧的臨時變量中存儲的是實參的副本;如果是自定義變量類型,則會在堆上創建該類型實例,復制該實參到堆上,然後將堆上該實例的地址壓入函數棧;如果是指針,則會將指針地址的副本(其實也可以認為這個保存這個指針的變量是基本變量類型)壓入函數棧。

  也就是說,函數棧上要麽保存的是一個基本類型參數的副本,要麽是個頂層指針。對於函數棧上保存的參數,實參的副本可以作為一個普通的局部變量,是可以修改值的,而對於指針變量,其可以視為頂層指針,本身的值不可以修改,但其指向的值可以修改。

  故而可知,對於基本變量類型,函數內部操作的是函數棧上的副本,不會對原值產生影響,對於類類型(非指針輸入性參數),操作的也是函數棧上的地址指向的實例副本,同樣不會對原值產生影響;而對於指針,函數內部雖然改變不了指針變量保存的指針值(該指針為頂層指針),但該指針卻指向的是原值的地址,故而能修改原值。

  對於引用,a)引用只是變量的一個別名,引用指向元變量內存地址,不會進行新的內存分配和變量的拷貝;b)引用聲明後必須馬上初始化;c)引用一經定義,不能改變其值,也就是不能再作為其它變量的引用; d)通過引用可以完全操作原變量。

  可以看出,當占空間很大的變量作為輸入型實參時,很適合用引用傳遞。因為用引用傳遞時,只是傳遞變量本身的一個別名,不會進行新變量的內存分配,構造,賦值,析構等操作。

  如果函數中不允許改變該實參,那麽就應該在引用參數上加const修飾。

  基於上述考慮。const修飾輸入型參數時,只需要修飾指針類型和引用類型即可(雖然不是強制,但對於輸入型指針或者引用參數用指針修飾應該成為一種習慣)。

  同時,這也說明一個編程時應該養成的習慣,對於輸入型參數,應該在函數起始位置定義一個局部變量接收該輸入型參數,而不是直接使用。

2. 對返回值的修飾。

  這個應用比較少。大部分返回值采用的時“值傳遞”。如果將返回值修飾為const,那麽接收返回值的變量也必須定義為const。

3. 對this指針的修飾。

  我們知道,c++成員函數在編譯時候,會傳入一個this指針,指向實例本身。這個this指針默認實際上是個頂層指針。即如果有classA,那麽這個指針其實類似如下的定義:

  classA * const this;

  即this指針指向實例本身並且不可以修改,但可以通過this指針修改其指向的成員變量。在成員函數內訪問成員變量m_var,實際上時如下形式方位的:

  this.m_var;

  如果我們設計一個成員函數時,不想讓其修改成員變量,那麽就應該將this指針定義為底層指針。c++定義的方式就是在函數簽名後面加上const,即

  void func(const A& a, int b, const int* c, int* d)const;

  顯然,上述成員函數中,a為const引用傳遞,不可以改變原值;b為值傳遞;c為const指針傳遞,不可改變原值;d為輸出參數,可以改變原值。而該函數為const成員函數,不可以修改成員變量值。

  以下是const成員函數註意的幾點

  1)const對象只能訪問const成員函數,而非const對象可以訪問任意的成員函數,包括const成員函數.即對於class A,有

  const A a;

  那麽a只能訪問A的const成員函數。而對於:

  A b;

  b可以訪問任何成員函數。

  2)const對象的成員變量不可以修改。

  3)mutable修飾的成員變量,在任何情況下都可以修改。也就是說,const成員函數也可以修改mutable修飾的成員變量。c++很shit的地方就是mutable和friendly這樣的特性,很亂。

  4)const成員函數可以訪問const成員變量和非const成員變量,但不能修改任何變量。檢查發生在編譯時。

  5)非const成員函數可以訪問非const對象的非const數據成員、const數據成員,但不可以訪問const對象的任意數據成員。

  6)const成員函數只是用於非靜態成員函數,不能用於靜態成員函數。

  7)const成員函數的const修飾不僅在函數聲明中要加(包括內聯函數),在類外定義出也要加。

  8)作為一種良好的編程風格,在聲明一個成員函數時,若該成員函數並不對數據成員進行修改操作,應盡可能將該成員函數聲明為const 成員函數。

const關鍵字對C++成員函數的修飾