1. 程式人生 > >C++中const與static使用的幾個要點

C++中const與static使用的幾個要點

(1) const使用要點

為什麼要使用const?

  1. const是定義常量的,而且const定義的常量是有資料型別的,而巨集常量是沒有資料型別的,所以編譯器可以對const常量進行型別安全檢查,而對巨集常量只是簡單的替換,沒有型別安全檢查,容易出錯。

  2. const起到保護的作用,防止修改。

  3. const還有一個關鍵作用是做函式過載。

  4. 節省空間:const定義的常量只是給出了對應的記憶體地址,而#define定義的常量在記憶體中有若干拷貝。

  5. 提高效率:編譯器通常不會為普通的const常量分配儲存空間,只是將他們儲存在符號表中,即它是一個編譯期間的常量,沒有儲存與讀取的操作,效率很高。

指標與const

  指標與const搭配的兩種形式:
  const int* p;   表示指向的內容是常量,不可變。
  int* const p;  表示這個指標本身是常量,不可變。
  const int* const p;  都不可變
 

const與引數傳遞

  1. const修飾引數的主要意義是引數在函式內不可以改變,所以對一般型別的形參修飾沒有意義。

  2. 如果形參是指標,const int* p這種修飾是有意義的,表明指標指向的內容是不能修改的,但int* const p是沒有意義的。

  3. const經常和引用一起用,表明引用的引數在函式內是不可以改變的,這和普通函式按值傳遞的效果相同,不同之處在於:按值傳遞是建立物件的副本,然後傳遞的,而常引用是直接傳遞地址,所以效率更高。

  4. const修飾函式返回值,是說函式的返回值是常量,不能修改。
    對返回值是指標時,則指向的內容不能被修改,且只能賦給const型指標
    如果返回值為某個物件為const或某個物件的引用為const ,則返回值具有const屬性,則返回例項只能訪問類a中的公有資料成員和const成員函式,並且不允許對其進行賦值操作,這在一般情況下很少用到。

  5. 注意一點,以下情況在c++中會被報錯為重複定義,而不是過載。

int fun1(int a,int b);
const int fun1(int a,int b);

const與類

  1. const修飾成員變數 只能在初始化列表中賦值,只有這一種賦值方法。

  2. const修飾成員函式,則該函式是不允許修改類的資料成員的。(注意:準確的來說是不允許改變非靜態資料成員,可改變靜態資料成員)

  3. 常物件只能呼叫被宣告為const的成員函式(構造與析構除外)。

class Screen{
    public:
        char get(int x,int y);
        char get(int x,int y)const;
};

const Screen a;
Screen b;
a.get(0,0);   //呼叫const成員函式
b.get(0,0);   //呼叫非const成員函式

  其實這個就是之前提到的基於const的函式過載。

(2)static使用要點

為什麼要用static

  1. 隱藏:當同時編譯多個檔案時,所有未加static字首的全域性變數和函式都具有全域性可見性。如果加了static,就會對其它原始檔隱藏。

    靜態全域性變數不能被其它檔案所用(全域性變數可以);其它檔案中可以定義相同名字的變數,不會發生衝突(自然了,因為static隔離了檔案,其它檔案使用相同的名字的變數,也跟它沒關係了);

    靜態函式跟靜態全域性變數的作用類似(靜態函式不能被其它檔案所用; 其它檔案中可以定義相同名字的函式,不會發生衝突;)

  2. 靜態區域性變數:延長變數的生存期。
    用於函式體內部修飾變數,這種變數的生存期長於該函式
    先說明下記憶體分佈的情況:對於一個完整的程式,在記憶體中的分佈情況如下: 

    • 棧區: 由編譯器自動分配釋放,像區域性變數,函式引數,都是在棧區。會隨著作用於退出而釋放空間。
    • 堆區:程式設計師分配並釋放的區域,new
    • 全域性資料區(靜態區):全域性變數和靜態便令的儲存是放在一塊的,初始化的全域性變數和靜態變數在一塊區域,未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域。程式結束釋放。
    • 程式碼區

    而靜態變數就是儲存在靜態區的,它隨著第一次函式的呼叫初始化,僅初始化這一次,第二次呼叫這個函式時不會再初始化,而是直接跳過,然後該變數不會隨著函式呼叫結束而銷燬。
    靜態區域性變數一般在宣告處初始化,如果沒有顯式初始化,會被程式自動初始化為0
    它始終駐留在全域性資料區,直到程式執行結束。但其作用域為區域性作用域,也就是不能在函式體外面使用它(區域性變數在棧區,在函式結束後立即釋放記憶體)

  3. 用於類:下面講

static與類

  1. 靜態資料成員:
    對於非靜態資料成員,每個類物件都有自己的拷貝。而靜態資料成員被當作是類的成員。無論這個類的物件被定義了多少個,靜態資料成員在程式中也只有一份拷貝,由該型別的所有物件共享訪問。對該類的多個物件來說,靜態資料成員只分配一次記憶體,供所有物件共用。

    靜態資料成員儲存在全域性資料區

    因為靜態資料成員在全域性資料區分配記憶體,屬於本類的所有物件共享,所以,它不屬於特定的類物件,在沒有產生類物件時其作用域就可見,即在沒有產生類的例項時,我們就可以操作它

    類的靜態資料成員有兩種訪問形式:
    <類物件名>.<靜態資料成員名> 或
    <類型別名>::<靜態資料成員名>

    靜態資料成員是靜態儲存的,所以必須對它進行初始化。(程式設計師手動初始化,否則編譯時一般不會報錯,但是在Link時會報錯誤)
    初始化在類體外進行,而前面不加static,以免與一般靜態變數或物件相混淆;
    初始化時不加該成員的訪問許可權控制符private,public等;
    初始化時使用作用域運算子來標明它所屬類;
    所以我們得出靜態資料成員初始化的格式:
    <資料型別><類名>::<靜態資料成員名>=<值>

    class A{
    public:
    static int a;
    };

    int A::a = 3; //初始化

  2. 靜態成員函式
    與靜態資料成員一樣,靜態成員函式為類的全部服務而不是為某一個類的具體物件服務。
    普通的成員函式一般都隱含了一個this指標,this指標指向類的物件本身,因為普通成員函式總是具體的屬於某個類的具體物件的。但是與普通函式相比,靜態成員函式不具有this指標。從這個意義上講,它無法訪問屬於類物件的非靜態資料成員,也無法訪問非靜態成員函式,它只能呼叫其餘的靜態成員函式

    呼叫靜態成員函式,可以用成員訪問操作符(.)和(->)為一個類的物件或指向類物件的指標呼叫靜態成員函式,也可以直接使用如下格式:
    <類名>::<靜態成員函式名>(<引數表>)
    呼叫類的靜態成員函式。

  3. const static int/static const int
    對於static const成員和const static成員而言,只有int型別可以在內部初始化,任何型別都可以在類外初始化,但是不可以在建構函式列表初始化。(static const int a=1;並不分配記憶體,編譯時直接將a換成1,放到常量表中)

總結c++類中特殊成員變數的初始化

#include <iostream>
using namespace std;

class BClass
{
public:
 BClass() : i(1), ci(2), ri(i){} // 對於常量型成員變數和引用型成員變數,必須通過引數化列表的方式進行初始化
                                                //普通成員變數也可以放在函式體裡,但是本質其實已不是初始化,而是一種普通的運算操作-->賦值運算,效率也低
private:
 int i;                                  // 普通成員變數
 const int ci;                           // 常量成員變數
 int &ri;                                // 引用成員變數
 static int si;                          // 靜態成員變數
 //static int si2 = 100;                 // error: 只有靜態常量成員變數,才可以這樣初始化
 static const int csi;                   // 靜態常量成員變數
 static const int csi2 = 100;            // 靜態常量成員變數的初始化(Integral type)    (1)
 static const double csd;                // 靜態常量成員變數(non-Integral type)
 //static const double csd2 = 99.9;      // error: 只有靜態常量整型資料成員才可以在類中初始化
};

//注意下面三行:不能再帶有static
int BClass::si = 0; // 靜態成員變數的初始化(Integral type)
const int BClass::csi = 1; // 靜態常量成員變數的初始化(Integral type)
const double BClass::csd = 99.9; // 靜態常量成員變數的初始化(non-Integral type)

// 在初始化(1)中的csi2時,根據著名大師Stanley B.Lippman的說法下面這行是必須的。
// 但在VC2003中如果有下面一行將會產生錯誤,而在VC2005中,下面這行則可有可無,這個和編譯器有關。
const int BClass::csi2;

int main()
{
     BClass b;
     return 0;
}

相關推薦

C++conststatic使用的要點

(1) const使用要點 為什麼要使用const? const是定義常量的,而且const定義的常量是有資料型別的,而巨集常量是沒有資料型別的,所以編譯器可以對const常量進行型別安全檢查,而對巨集常量只是簡單的替換,沒有型別安全檢查,容易出錯。

C++const引用,指標之間的關係要點

一、const關鍵字 1、有時我們希望定義這樣的一個變數,它的值不能被改變。這時就可以在定義變數時加上const關鍵字。例如 const int bufSize=512; const型別變數可以進行大部分與非const型別變數相同操作,主要的限制就是不可以在const型別的物件上執

C++conststatic,inline的用途

ue4 dba pac use lzw fsm 強硬 oci jce G7U42mcs62卸ehttp://www.docin.com/app/user/userinfo?userid=180985862 閱惶0欠4r肝6置gw人http://docstore.docin

C++const指標、引用的總結

C++中函式的引數相比C語言中的函式引數要複雜的多,其中主要的原因是C++中引入了引用以及const限定符。這兩個物件的引入,使得C++中的函式引數變得異常的複雜多變,每一種型別都具有比較適合的使用範圍。 一,引用 引用是物件的別名,必須在初始化的過程中與一個具體的物件繫

Adobe Animate必須掌握的要點

Adobe Animate脫胎於Flash編輯器,這個由MacroMedia公司原創的flash曾經風靡一時,後面更是在Abode收購後大放異彩,甚至都出現了以此為生的“閃客”的出現,但其安全漏洞成了其難以隔去的闌尾,實際上是屢次更新也無法徹底解決,像蘋果、谷歌、微軟這樣的主流廠商,很早

C++conststatic修飾場景描述

         在c++中,     static可以在兩種情景下使用,分別是類外和類內; 其中類外的修飾物件可以是區域性變數和全域性變數,被

C++】C++constconstexpr的比較

先說結論相同點:const和consexpr都是用來定義常量的。不同點:const宣告的常量,初始值引用的物件不一定是一個常量;constexpr宣告的常量,初始值一定是常量表達式。   constexpr是c++11標準新增的關鍵字。   之所以說const宣告的常量,初始值不一

phpconststatic的區別使用

首先關於const 在php的類內部只可以修飾成員屬性,不可以修飾方法,如下:class Test{ const PATH = 'c/';//修飾常量 const function test(){//這種方法是錯誤的,const無法修飾方法 } } const在使用的

iOSconststatic區別和聯絡

const就是隻讀的意思,只在宣告中使用; static一般有2個作用,規定作用域和儲存方式.對於區域性變數,static規定其為靜態儲存方式,每次呼叫的初始值為上一次呼叫的值,呼叫結束後儲存空間不釋放; 對於全域性變數,如果以檔案劃分作用域的話,此變數只在當前檔案可見;對

理解OpenStack的OpenvSwitch的要點

OpenvSwitch是實現虛擬化網路的重要基礎元件,在OpenStack中利用OpenvSwitch作為底層部件來完成虛擬網路提供和租戶網路管理。 在部署和應用OpenStack的過程中,可能會碰到網路相關的一些問題,能夠準確的理解OpenStack中OpenvSwitc

預處理、conststaticsizeof-C++const有什麽作用(至少說出3

什麽 需要 char 修改 抽象 ons 時間 數據 amp 1:作用如下: (1)const用於定義常量:const定義的常量編譯器可以對其進行數據靜態類型安全檢查。 (2)const修飾函數形式的參數:當輸入參數為用戶自定義類型和抽象數據類型時,應該將“值傳遞”改為“c

C程式設計使用到的重要關鍵字之一const

  1)、這個問題討論的是“常量”與“只讀變數”的區別。常量肯定是隻讀的,例如5, "abc",等,肯定是隻讀的,因為常量是被編譯器放在記憶體中的只讀區域,當然也就不能夠去修改它。而“只讀變數”則是在記憶體中開闢一個地方來存放它的值,只不過這個值由編譯器限定不允許被修改。C語言關鍵字const就是用來限定一個

jQuery的$(window)$(document)用法區別

圖片 document window function 準備就緒 [window對象] 它是一個頂層對象,而不是另一個對象的屬性,即表示瀏覽器中打開的窗口。 1、屬性  defaultStatus 缺省的狀態條消息  document 當前顯示的文檔(該屬性本身也是一個對象)  f

C/C++const關鍵字的用法及其宏定義的比較

類型安全 屬性 const關鍵字 code oid 程序 函數返回值 存儲空間 臨時對象 1.const關鍵字的性質 簡單來說:const關鍵字修飾的變量具有常屬性。 即它所修飾的變量不能被修改。 2.修飾局部變量 1 const int a = 10; 2 int co

C++】CC++ const常量 - 修改時報錯

#include <stdio.h> #define PAUSE printf("Press Enter key to continue - By WangLei ..."); fgetc(stdin); int main() { const int n = 10; // &

C#物件的關係,以及方法申明的static修飾符

C#中,類(class)的書寫,是class 類名稱:例如class Program這就是一個Program類,類理解起來就是同一類事物,具有同樣的特性,就如同我們常說的人類,鳥類,這樣具有相同特性和行為的一類事物的統稱,在程式設計中這種特性我們可以把它用一些方法功能來表示,例如程式:

C++const char*, string char*的轉化

1:string轉化成const char* 可以通過呼叫string類中的c_str函式實現string向const char*的轉換 //string與const char*轉換 string s = "string_To_const char* "; const c

C++defineconst的區別

C++中不但可以用define定義常量還可以用const定義常量,它們的區別如下: 用#define MAX 255定義的常量是沒有型別的,所給出的是一個立即數,編譯器只是把所定義的常量值與所定義的常量的名字聯絡起來,define所定義的巨集變數在預處理的時

Objective C執行時(runtime)技術的要點總結

前言: Objective C的runtime技術功能非常強大,能夠在執行時獲取並修改類的各種資訊,包括獲取方法列表、屬性列表、變數列表,修改方法、屬性,增加方法,屬性等等,本文對相關的幾個要點做了一個小結。 目錄:   (6) 總結 (1)在執行時對函式進行動態替換 : cl

c語言定義變數的關鍵字

1.auto (1)auto關鍵字在C語言中只有一個作用,那就是修飾區域性變數。 (2)auto修飾區域性變數,表示這個區域性變數是自動區域性變數,自動區域性變數分配在棧上。(既然在棧上,說明它如果不初始化那麼值就是隨機的······) (3)平時定義區域性變數時就是定義的a