C 第二章(資料型別)之四

2021-04-01 02:55:59 字數 4351 閱讀 3827

常量const允許我們在變化和不變之間劃清一條界限.

const設計的最初動機就是取代預處理器#define進行值替代.從此其應用範圍包括指標,函式變數,返回型別,類物件以及成員函式.

const應用1: 值替代:

c語言中典型使用預處理器進行值替代典型的用法:

#define bufsize  100;

bufsize 是乙個名字,它不占用儲存空間而且可以放在乙個標頭檔案中,目的是為使用它的所有的編譯單元提供乙個數值.

特點:用c語言進行程式設計的時候,預處理器可以不受限制的建立巨集並且用它來代替值.因為

預處理器只做文字替換,它既沒有型別檢查的思想,也沒有型別檢查的工具,就為其代替的數混亂產生伏筆.

const

的出現就是為了讓#define有更加安全的保證.

標頭檔案裡面的

const

與#define一樣,使const必把const放到標頭檔案裡.這樣通過包含標頭檔案,可以把const定義單獨放在乙個地方並且把它分配給乙個編譯單元.

c++中的const預設的是內部連線,也就是說:const僅在const被定義過的標頭檔案裡面才是可見的,而在連線時不能被其他變異單元看到。

當定義乙個const常量的時候,必須賦值給他,除非用extern說明:extern const bufsize

雖然上面的extern強迫編譯器進行了儲存空間分配,但是c++編譯器通常不為const分配空間的,相反把這個定義儲存在它的符號表裡面,當const使用的時候,他在編譯器時會進行常量摺疊。

當然,對於複雜的機構來講編譯器是要分配儲存的,這種情況下,編譯器建立儲存,這樣會防止常量摺疊。這就是為什麼const必須v預設是內部連線,即連線僅在特別編譯單元的原因。否則,由於眾多的const在多個cpp檔案內分配儲存,容易引起連線錯誤,連線程式在多個物件檔案裡面看到同樣的定義就會「抱怨」。然而,因為const預設內部連線,所以連線程式vbuhui 跨越 編譯單元連線那些定義,因此不會衝突。對於在大量場合使用的內部資料型別包括常量表示式,編譯器都會進行常量摺疊。

const安全性:

const的作用不限於在常量表示式裡代替#defines。如果用執行期間產生的值初始化乙個變數而且知道在那個變數壽命期間內它是不變的,用const限定該變數,程式設計中這是乙個很好的做法。

實際上,如果想乙個值不變,就應該使之成為常量(const).這不僅為防止意外的更改提供安全措施,也是消除儲存和記憶體操作,使編譯器產生的**更有效.

集合:const可以用集合,但是編譯器不能把乙個集合放在他的符號表裡面,所以必須分配記憶體,在這種情況下,const意味著不能改變的一塊兒記憶體.然而其值在編譯期間不能被使用,因為編譯器在編譯時不需要知道儲存內容.

const應用2:

引用對於變數來說是變數的別名。對其操作就是對所代表的變數操作。

i: 指標

我們還可以使指標成為conost,當處理const指標時,編譯器仍將努力阻止儲存分配並進行常量摺疊.但是在這種情況下,這些特徵似乎很少用,更重要的是,如果以後程式設計師想在**中改變這種指標的使用,編譯器會給出通知,這樣大大的增加了安全性.

當使用帶有指標的const時,有兩種做法:或者const修飾指標正指向的物件或者const修飾儲存在指標本身的位址裡.

1: 指向const的指標

const int* x;                          //其正指向的元素不發生變化

x是乙個指標,它指向乙個const int.這裡不需要初始化,因為說x可以指向任何東西,但是它指向的東西是不能被改變的.

int const* x;

x是乙個指向恰好是const的int普通指標.

2:const指標

使指標本身成為乙個const指標,必須把const標明的部分放在*右邊。

int d;

int* const x = &d;                         //指標本身不變

x是乙個指標,這個指標是指向int的const指標。

注意: 不管在任何的時候,在同一行存放乙個指標的定義,並且在定義的地方初始化每個指標.正是因為這一點才把 "*" 賦於資料型別之上.事實上"*"是與識別符號結合的.

ii: 函式引數和返回值

如果以值傳遞物件時候,對於使用者來講,用const來講是沒有任何意義的。如果以常量返回使用者定義型別的乙個物件的值,這意味著返回值不能被修改。如果傳遞或返回位址,const將保證位址內容不會被改變。

a:傳遞const值

如果是以值傳遞的,可以用const限定函式引數。引數是以值傳遞的,因此要立即製作變數的副本(這個約定對於使用者來說是隱藏的)。

在函式裡,const有這樣的定義:引數不能被改變。所以它其實是函式建立者的工具,而不是函式呼叫者的工具。

在函式內部呼叫const限定引數優於在參數列裡面用const限定引數。

b:返回const值

返回乙個內部資料型別沒有必要用const修飾,因為編譯器不會讓它成為乙個左值(因為它總是乙個數值而不是乙個變數)。所以如果不想讓自定義型別作為左值就要使用const修飾。

所有的臨時變數都是自動成為常量。

為了防止修改指標(引用)的初值,使用const修飾。事實上,無論何時我們使用乙個指標,我們都使用const來修飾它。

編譯器不允許把存放在const指標裡面的位址來建立乙個非const指標。

d:標準值傳遞

c語言中,值傳遞時很普通,但是要傳遞位址的時候就要用指標了。

在c++中傳遞乙個引數的時候,首先想到的是引用傳遞,而且是通過常量(const)引用的傳遞。如果通過常量const引用來傳遞,這意味著函式將不能夠改變該位址的內容,其實和值傳遞相同。

由於引用語法的原因,傳遞乙個臨時變數給帶有乙個引用的函式是可能的,但是不可以傳遞乙個臨時物件給帶有乙個指標的函式---因為它必須清楚地帶有位址,所以會出現以下情況:乙個總是常量的臨時變數,他的位址可以被傳遞給乙個函式。

例子說明:

iv類a:在乙個類裡面使用const的意義是:在這個物件壽命期內,這是個常量。然而對於這個常量來講,乙個類的不同常量可以含有乙個不同的數值。

在乙個類裡面建立乙個const時候,不能夠給他初值。這個初始化的工作必須建立它的地方初始化,在建構函式的主題裡面,const必須已經初始化了(因為在函式裡裡面他何以在任何地方初始化,這樣無法阻止在建構函式的不同的地方改變const數值),所以必須在建構函式的初始化列表裡面初始化,其行為發生在建構函式的任何**執行之前。

class fred

;fred::fred() : size(100)  {}

fred::fred(int i) : size(i)  {}

b:編譯期間的常量

類中的const意思是在這個特定物件壽命期間,而不是對於這個類來說是const.。如果要保證類中的常量,而且是編譯期間求職需要是enum;

class bunch

int i[size];

};c:const物件和成員函式

const物件和const成員函式是密不可分的。如果宣告乙個成員函式為const函式,則等於告訴編譯器可以為乙個const物件呼叫這個函式。乙個沒有特別宣告為const的成員函式被看成是將要修改物件中資料成員的函式,而且編譯器不會被允許乙個const物件呼叫這個函式。

同inline類似,const標識的函式需要

在定義時候強調。

//#include

#include

#include

using namespace std;

class quoter

;quoter::quoter()

int quoter::lastquote() const

const char* quoter::quote()

;const qsize = sizeof quotes/sizeof* quotes;

int qnum = rand() % qsize;

while( lasquote >=0 && qnum == lasquote )

qnum = rand() % qsize;

return quotes[ lasquote = qnum ];

}int main()

void f() const;

};public void  y::f() const

void main()

還有一種方法是使用

mutable來修飾變數來表示其在const函式裡面可以改變其值。

class y

void f() const;

};public void  y::f() const

void main()

說明:關鍵字const能夠將物件,函式引數,返回值以及成員函式定義為常量,並且能消除預處理的值替代而不對預處理器產生任何影響。所有這些都為程式設計提供了非常好的型別檢查形式以及安全性。使用所謂的const correctness(在可能的地方使用const)已經為專案的救星了.

第二章 資料型別

1byte 8bit 1kb 1024byte 1mb 1024kb 1gb 1024mb 1tb 1024gb intfloat 用float計算精度會不準確,需要匯入decimal模組 strbool true,false int 可以將整數型的str和float,bool轉換成int str ...

第二章 深入C 資料型別

資料型別按儲存方式可分為兩類 值型別 源於system.valuetype 引用型別 源於system.object 結構的定義 結構中可以有字段也可以有方法 定義時,結構中的字段不能被賦初值 結構的使用 可以不用new,直接定義結構的物件即可 前提該屬性的型別不是數值型別 宣告結構的物件後,必須給...

Python第二章資料型別

基本資料型別 python 中的變數不需要宣告。每個變數在使用前都必須賦值,變數賦值 以後該變數才會被建立。python 中,變數就是變數,它沒有型別,我們所說的 型別 是變數所指的記憶體中物件的型別。等號 用來給變數賦值。等號 運算子左邊是乙個變數名,等號 運算子右邊是儲存在變數中的值。例如 x ...