1. 程式人生 > >const和static const的區別

const和static const的區別

一、const關鍵字

如果把const放在變數型別名前,說明這個變數的值是保持不變的,該變數必須在定義時初始化,初始化後對它進行的任何賦值都是非法的。

當指標或者引用指向一個常量時,必須在型別名前使用const標識這個指標或者引用指向的“變數”為常量,沒有的話就是語法錯誤。如: const int x = 5;      const int* px = &x;     const int& rx = x;這樣一來,直接修改x是不可能的,通過*px或者rx修改x也是不可能的。當然,這個指標還能指向其他的地方,因為指標本身並沒有被標識為const的。比如,px = &y;

假如變數是一個非常量變數,而指標或者引用的型別名前使用了const,那麼,可以直接修改變數,不能通過指標或者引用修改變數。


如果想讓一個指標本身成為const的,就要在*後加const,即int* const p = &x;這個時候,p就不能再指向其他變數。假如x是非常量的,那它可以通過指標進行修改,因為x並沒有標識為const。當然,引用天生就是const的,它必須被初始化,而且初始化後就不能再指向新的變數。比如,int x = 5; int& r = x; r = y;第二句程式碼不會讓r指向y,而是讓x的值變成了y。

如果在函式介面(引數)中使用const,和在值、指標中使用是類似的。但是,這就更難讓函式返回指向這個引數物件的指標或者引用了。如果允許的話,客戶程式碼就有可能通過別名修改常量。比如,


class Point

{

    int x, y;

public:

    Point closestPointVal(const Point& pt)

    { if( x*x+y*y < pt.x*pt.x+pt.y*pt.y)

        return *this;

    else return pt;}

    Point* closestPointPtr(const Point& pt)

    {   return (x*x+y*y < pt.x*pt.x+pt.y*pt.y) ? this : &pt;}

   Point& closestPointRef(const Point& pt)


    {   return (x*x+y*y < pt.x*pt.x+pt.y*pt.y) ? *this : pt;}

};

第一個函式是返回值的,不管用不用const,都不會修改實參pt。而第二個函式可以返回指向pt實參的指標。客戶程式碼就可以使用這個指標修改實際引數物件的狀態。同樣,第三個函式返回的引用也能修改實參物件的狀態。假如這樣的函式是合法的,那麼就有可能誤用,誤用後如果出了錯,很難弄清是這裡出的錯,所以編譯程式直接就認為這樣的函式不合法。也就是,引數物件使用了const,而返回型別沒有,這是錯誤的。

C++提供了三種方法解決這個問題:1.引數不使用const;2.在成員函式內部,使用const_cast運算子移去const屬性;3.在另外合適的地方新增const。一個真正的程式設計師是不會放過任何一個機會,將設計人員的設計意圖傳達給客戶程式碼程式設計師和維護人員的。所以,假如某個引數沒有被修改,就要用const來明確說明。而使用const_cast也很糟糕,不易理解。所以只能使用第三種方法,在函式返回值前加上const,接收該返回值的指標或者引用也要是const的。這樣的話,返回值只能作為右值,不能作為左值。這樣的返回值不能呼叫它所在類的成員函式。

C++提供const關鍵字,不是為了保證一個變數不被修改,而是為了方便編譯程式和維護人員弄清楚一個實體在程式中是否被修改了。如果函式介面中宣告引數為const,我們就認為這個引數不會改變,如果沒有宣告為const,就認為這個引數一定被改變了,而不管函式到底有沒有改變這個引數。

其實,const還有一個含義,就是在函式的引數列表的“)”之後,函式體的“{”之前。這種用法說明函式不會修改目標物件的值。

二、靜態類成員

每建立一個類物件例項,都會為該例項建立一個單獨的資料成員集合。不管是將物件定義為有名的區域性變數,有名的全域性變數,或者使用new定義為未命名的動態變數,或者按值傳遞一個物件作為函式引數,或者從一個函式按值返回一個物件。而對於成員函式,它們的目的碼卻只產生一次。因為每個程式函式都有一個隱含的引數,即this指標。

1 用全域性變數作為類特性

類為物件例項提供了一個藍圖或者說是模板,類的成員變數都是這個類的所有例項的共性,類的每一個例項都有一個單獨的副本。但是有時我們需要為一個類的所有例項提供共有的資料成員副本,這比在每個類物件中維護單獨的副本能更有效的合理利用記憶體。最常見的例子就是對類的例項進行計數。假如這個計數變數count被定義在類中,在建構函式中對其加1,在解構函式中對其減1,似乎能實現計數作用。但是實際上卻是做不到的。因為count是類的成員變數,每個例項都有一個count,建構函式對其加1,只是對自己的count加了1。

使用全域性變數就能解決這個問題。但是將它用在大型程式中,存在一些問題,這些問題在前面都講過了。首先在客戶程式碼任意地方都可能使用count,增加了模組之間的依賴性。其次,全域性變數名增加了重名機會。最重要的是,count作為全域性變量出現時,維護人員不能很好的瞭解它是做什麼的,除非看註釋或者查閱大量其他程式碼。

2 static的含義

static和const一樣很複雜。

首先,將static用於一個全域性變數,是說明該全域性變數只對定義在同一個檔案中的函式可見。即使在另一個檔案中使用了extern,另一個檔案中的函式也不能訪問這個全域性變數。

static的第二個含義是用於一個函式前,說明該函式只能在同一個檔案中呼叫。

第三個含義是static用於函式的區域性變數。它表明該變數的值不會因為函式終止而消失,它會被儲存下來。再次呼叫該函式時,這個儲存下來的值會用來初始化該變數。

第四個含義就是用於類的成員變數。它表明對類的所有物件,這個資料成員都只有一個例項。這個例項被所有物件共有。static的成員變數可以是private、public、protected的。定義和訪問的語法也和其他資料成員一樣。

3 靜態資料成員的初始化

靜態資料成員在類規格說明外部被初始化,這一點和全域性變數相似。但是全域性變數可以被隱式地初始化為0,而靜態成員變數作為類的資料成員,必須被顯式地初始化,因為類的所有的資料成員都必須被顯式初始化。賦值和初始化存在著重要的區別,如果型別名後緊跟著變數名,就是初始化,如果變數名前沒有型別名,就是賦值。初始化對於公共的和非公共的靜態資料成員是合法的,但是對非公共的靜態資料成員進行賦值卻是不合法的。比如,如果count是private的,那麼Point::count = 0就是錯誤的。

靜態資料成員只能被初始化一次,所以它應該和其他的成員函式的定義一起放在.cpp檔案中,而不能放在標頭檔案中。一個靜態資料成員不能是聯合的成員,也不能是位域的類。聯合和位域都表示屬於某個特定物件的特殊記憶體用途,而靜態資料成員卻不屬於特定物件,它屬於整個類。

4 靜態成員函式

static的第五種含義是用在類的成員函式前,表明這個函式不訪問非靜態資料成員,它只能訪問它的引數、類的靜態資料成員、全域性變數。注意到靜態成員函式訪問的三種類型的資料,都不是描述物件狀態的。而在函式引數列表後面使用const表明該函式不會修改該函式的目標物件的資料成員。所以,一個靜態成員函式沒有必要在引數列表之後新增一個const。

靜態成員函式可以通過物件來呼叫,也可以直接使用類名來呼叫。因為它是類的特性,而不是物件的性質。

定義類的某個資料成員為靜態變數,以表明此全域性資料邏輯上屬於該類。定義類的成員函式為靜態函式,表明此全域性函式邏輯上屬於該類,而該函式只對靜態資料、全域性資料、引數進行操作。

相關推薦

conststatic const區別

一、const關鍵字如果把const放在變數型別名前,說明這個變數的值是保持不變的,該變數必須在定義時初始化,初始化後對它進行的任何賦值都是非法的。當指標或者引用指向一個常量時,必須在型別名前使用const標識這個指標或者引用指向的“變數”為常量,沒有的話就是語法錯誤。如: const int x = 5; 

C++ staticconststatic const型別成員變數宣告及其初始化

C++ static、const和static const型別成員變數宣告及其初始化 const定義的常量在超出其作用域之後其空間會被釋放,而static定義的靜態常量在函式執行後不會釋放其儲存空間。 static表示的是靜態的。類的靜態成員函式、靜態成員變數是和類相關的,而不是和類的具

C++ staticconststatic const型別成員變數宣告以及初始化

下面的文章是我從網上找了好久,整理了好久的,對我有很大幫助,原址已經記不住了,算我自己原創的了哇! const定義的常量在超出其作用域之後其空間會被釋放,而static定義的靜態常量在函式執行後不會釋放其儲存空間。 static表示的是靜態的。類的靜態成員函式、靜態成員變

C++學習 之 staticconststatic const

const定義的常量在超出其作用域之後其空間會被釋放,而static定義的靜態常量在函式執行後不會釋放其儲存空間。static表示的是靜態的。類的靜態成員函式、靜態成員變數是和類相關的,而不是和類的具體物件相關的。即使沒有具體物件,也能呼叫類的靜態成員函式和成員變數。一般類的

c++的conststatic區別

const定義的常量在超出其作用域之後其空間會被釋放,而static定義的靜態常量在函式執行後不會釋放其儲存空間。 static表示的是靜態的。類的靜態成員函式、靜態成員變數是和類相關的,而不是和類的具體物件相關的。即使沒有具體物件,也能呼叫類的靜態成員函式和成員變數。一般

const、define static區別

[TOC] # define、const 在 C++ 中,const 和 define 都可以用來定義常量。但是這二者之間有很大的區別: * define 的作用 用 define 定義的常量是沒有 **型別** 的,編譯器只是把所定義的常量值和這個常量的名字聯絡起來,編譯器在編譯的過程中只是把

C++編程中const#define的區別

程序 存在 pan best color 普通 分配 一次 def (1) 編譯器處理方式不同  define宏是在預處理階段展開。  const常量是編譯運行階段使用。(2) 類型和安全檢查不同  define宏沒有類型,不做任何類型檢查,僅僅是展開。  const常量有

constreadonly的區別

編譯器優化 時也 定義 不足 bsp mce 包括 優化 運行 1.const、readonly和static readonly定義的常量,指定初始值後(包括在構造函數內指定的初始值) 將不可更改,可讀不可寫;2.const定義時必 須指定初始值,而readonly定義時可

C語言constdefine的區別

一份 安全 font 預處理 tro span ble 展開 區別 const 定義的是變量不是常量,只是這個變量的值不允許改變是常變量!帶有類型。編譯運行的時候起作用存在類型檢查。 define 定義的是不帶類型的常數,只進行簡單的字符替換。在預編譯的時候起作用,不存在類

C++ const static的總結以及使用

局部變量 數值 功能 const 常量 指針 main this指針 同名 this 一 static的使用 (作用域和存儲方式) 1.作用域---------->隱藏 靜態函數跟靜態全局變量的作用類似 (靜態函數不能被其它文件所用; 其它文件中可以定義相同名字的函

javascript中的let 、const var 的區別

在JavaScript中有三種宣告變數的方式:var、let、const。下文給大家介紹js中三種定義變數的方式const, var, let的區別 1.let和const中不存在變數提升,var中存在變數提升 console.log("a----" + a); var

const關鍵字以及const#define的區別

1.const - 1.const修飾變數、引數、返回值: 在C++中const修飾變數,使變數變成常量,在宣告的同時必須初始化;C++的const修 飾的全域性變數可以作為屬組的初始化的大小,而C不可以,同時變數的值不能被修改;C++利用const的這一屬性,代替C中的

varconstlet的區別

主題大綱:ES6 系列之 let 和 const 簡述: 1.前端的變數申明,可以用到var,ES6的const(衡量)/let(變數) 2.在ES5用的都是var,到ES6之後,也就是2015年開始出現const/let. var 不會報錯,有宣告提升,會顯示undefined(一個變數未初始化)

C++中conststatic修飾場景描述

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

C++面試題——const static

雖說不太喜歡這種問語言特性的題目,但是國內好多公司貌似就喜歡問這個,還覺得問這個很高階,就把他們常問的一些東西寫下來做個總結,有的東西還是有些意思的,有些東西其實都沒個固定的答案。不出意外將會寫一個系列包括: const和static的區別iterator和引用的實現以及

C++ const constexpr 的區別

語義上: constexpr:告訴編譯器我可以是編譯期間可知的,盡情的優化我吧。 const:告訴程式設計師沒人動得了我,放心的把我傳出去;或者放心的把變數交給我,我啥也不動就瞅瞅。 語法上: constexpr是一種比const 更嚴格的束縛, 它修飾的表示式本身在編譯期間可知, 並且編譯器會盡可能的 e

ES6入門教程筆記(2)-let、constvar的區別

1 let命令 ES6新增了let命令,用來宣告變數。它的用法和var類似,但有以下幾點區別: let宣告的變數,只在所在的程式碼塊內有效。 let宣告的變數,一定要在聲明後才能使用,否則報錯。 不允許在相同作用域內,重複宣告同一個變數。 2 塊級作

php中conststatic區別與使用

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

php constdefine的區別(php類中如何定義常量)

大家都知道define是定義常量的,如果在類中定義常量呢?當然不能用define,而用const,如下例: <?php//在類外面通常這樣定義常量define("PHP","phpddt.com");classMyClass{//常量的值將始終保持不變。在定義和使

C語言中關鍵字作用(conststaticextern)

儲存型別關鍵字(4個): auto: 宣告自動變數,現在一般不用(auto int a;和int a;一樣) register: 宣告暫存器變數 static: 宣告靜態變數。該變數宣告時系統所分配的