const 詳解(修飾變量、輸入參數、返回值、成員函數)

C語言函數中的參數有const的問題,具體代碼以下

照理說有const的參數怎麼還能執行*strDest++=*strSrc++;呢 請大師解答c++

char* Copy(char* strDest,const char* strSrc)
{
char* strDestCopy = strDest;
while (*strSrc!='\0')
{
*strDest++=*strSrc++;
}
return strDestCopy;
}

首先,你得先區分const char* a和char* const a的區別。 一個是把指針定爲const 。就是不能修改指針。也就是char * const p 一個是把指針指向的內容定爲const 。就是不能修改指針指向的內容 也就是const char p 在這裏,const char strSrc表示的是不能修改指針指向的內容,可是對於*strDest++=*strSrc++; 只是在修改指針strSrc的指向,因此是能夠成立而且執行的,不明白繼續追問程序員

C語言中const有什麼用途

是一道專接本的簡答題,要求至少說出兩種const的用途函數

還有一道題是軟件測試都有哪些種類 請高手幫忙 fsyss1314 | 瀏覽 162269 次 發佈於2015-05-17 22:48 最佳答案測試

const修飾的數據類型是指常類型,常類型的變量或對象的值是不能被更新的。設計

const關鍵字的做用主要有如下幾點:指針

(1)能夠定義const常量,具備不可變性。 例如: const int Max=100; int Array[Max]; (2)便於進行類型檢查,使編譯器對處理內容有更多瞭解,消除了一些隱患。例如: void f(const int i) { .........} 編譯器就會知道i是一個常量,不容許修改; (3)能夠避免意義模糊的數字出現,一樣能夠很方便地進行參數的調整和修改。 (4)能夠保護被修飾的東西,防止意外的修改,加強程序的健壯性。 仍是上面的例子,若是在函數體內修改了i,編譯器就會報錯; 例如: void f(const int i) { i=10;//error! } (5) 爲函數重載提供了一個參考。 class A { ...... void f(int i) {......} //一個函數 void f(int i) const {......} //上一個函數的重載 ...... }; (6) 能夠節省空間,避免沒必要要的內存分配。 例如: #define PI 3.14159 //常量宏 const doulbe Pi=3.14159; //此時並未將Pi放入ROM中 ...... double i=Pi; //此時爲Pi分配內存,之後再也不分配! double I=PI; //編譯期間進行宏替換,分配內存 double j=Pi; //沒有內存分配 double J=PI; //再進行宏替換,又一次分配內存! const定義常量從彙編的角度來看,只是給出了對應的內存地址,而不是象#define同樣給出的是當即數,因此,const定義的常量在程序運行過程當中只有一份拷貝,而#define定義的常量在內存中有若干個拷貝。 (7) 提升了效率。 編譯器一般不爲普通const常量分配存儲空間,而是將它們保存在符號表中,這使得它成爲一個編譯期間的常量,沒有了存儲與讀內存的操做,使得它的效率也很高。code

看到const關鍵字,程序員首先想到的多是const 常量。

const 更大的魅力是它能夠修飾函數的參數、返回值,甚至函數的定義體。對象

const 是constant 的縮寫,「恆定不變」的意思。被const 修飾的東西都受到強制保護,能夠預防意外的變更,能提升程序的健壯性。因此不少C++程序設計書籍建議:「Use const whenever you need」。內存

##1、const 修飾函數的參數get

若是參數做輸出用,不論它是什麼數據類型,也不論它採用下文討論的「指針傳遞」仍是「引用傳遞」,都不能加const 修飾,不然該參數將失去輸出功能。const 只能修飾輸入參數,這又分爲如下幾種狀況。

1.1 const 用於修飾「指針傳遞」的參數,以防意外改動指針所指數據

例如某個 StringCopy 函數:

void StringCopy(char *strDestination, const char *strSource);

其中 strSource 是輸入參數,strDestination 是輸出參數。給 strSource 加上 const 修飾後,若是函數體內的語句試圖改動 strSource 的內容,編譯器將指出錯誤。

固然也有方法繞過這個限制,例如能夠在函數體內重命名一個指針 char * strSource2 = strSource ; 便可改動 strSource 所指的數值。

1.2 const 用於修飾「指針傳遞」的參數,以防意外改動指針自己

考慮以下代碼:

void swap ( int * const p1 , int * const p2 )

該定義將限制在函數 swap 內修改指針 p1 和 p2 的指向。

1.3 值傳遞的效率問題

若是輸入參數採用「值傳遞」,因爲函數將自動產生臨時變量用於複製該參數,該輸入參數原本就無需保護,因此不要加const 修飾。

例如不要將函數 void Func1 (int x) 寫成 void Func1(const int x)。同理不要將函數 void Func2(MyClass a) 寫成void Func2(const MyClass a)。其中 MyClass 爲用戶自定義的數據類型。

然而,對於非內部數據類型的參數而言,相似 void Func(MyClass a) 這樣聲明的函數效率會比較底,這是由於函數體內將產生MyClass類型的臨時對象用於複製參數a,而臨時對象的構造、複製、析構過程都將消耗時間。

爲了提升效率,能夠將函數聲明改成void Func (MyClass &a),由於「引用傳遞」僅借用一下參數的別名而已,不須要產生臨時對象。

可是函數void Func(MyClass & a) 存在一個缺點:「引用傳遞」有可能改變參數a,這是咱們不指望的。

解決這個問題很容易,加const修飾便可,所以函數最終成爲void Func(const MyClass &a)。

以此類推,是否應將void Func(int x) 改寫爲void Func(const int &x),以便提升效率?

答案是徹底沒有必要,由於內部數據類型的參數不存在構造、析構的過程,而複製也很是快,「值傳遞」和「引用傳遞」的效率幾乎至關。因此對於內部數據類型的輸入參數,不要將「值傳遞」的方式改成「const 引用傳遞」。不然既達不到提升效率的目的,又下降了函數的可理解性。

##2、const 修飾函數的返回值

2.1 const 修飾函數返回值(返回指針)

若是給以「指針傳遞」方式的函數返回值加 const 修飾,那麼函數返回值(即指針)的內容不能被修改,該返回值只能被賦給加const 修飾的同類型指針。

例如函數

const char * GetString(void);

以下語句將出現編譯錯誤:

char *str = GetString();

正確的用法是

const char *str = GetString();

2.2 const 用於修飾「返回引用」函數的返回值

若是函數返回值採用「值傳遞方式」,因爲函數會把返回值複製到外部臨時的存儲單元中,加const 修飾沒有任何價值。例如把函數int GetInt(void) 寫成const int GetInt(void)是沒有意義的。

若是返回值不是內部數據類型,將函數MyClass GetObj(void) 改寫爲const Myclass & GetObj(void)的確能提升效率。但此時千萬千萬要當心,必定要搞清楚函數到底是想返回一個對象的「拷貝」仍是僅返回「別名」就能夠了,不然程序會出錯。

這裏對函數返回值使用 const 的目的在於限制不能將函數調用表達式做爲左值使用。例若有以下函數:

int & min ( int &i, int &j);

能夠對函數調用進行賦值,由於它返回的是左值: min ( a , b )=4;

可是,若是對函數的返回值限定爲 const 的,即丁奕:const int & min ( int & i, int &j );

那麼,就不能對 min ( a, b ) 調用進行賦值了。

事實上,函數返回值採用「引用傳遞」的場合並很少,這種方式通常只出如今類的賦值函數中,目的是爲了實現鏈式表達。

例如:

class A
{
A & operate = (const A & other); // 賦值函數
} ;
A a, b, c; // a, b, c 爲A 的對象
a = b = c; // 正常的鏈式賦值
(a = b) = c; // 不正常的鏈式賦值,但合法

若是將賦值函數的返回值加const 修飾,那麼該返回值的內容不容許被改動。上例中,語句 a = b = c 仍然正確,可是語句 (a = b) = c 則是非法的。

3、const 用於修飾成員函數

const 成員函數的聲明看起來怪怪的:const 關鍵字只能放在函數聲明的尾部,大概是由於其它地方都已經被佔用了。

但事實上,任何不會修改數據成員(即函數中的變量)的函數都應該聲明爲const 類型。若是在編寫const 成員函數時,不慎修改了數據成員,或者調用了其它非const 成員函數,編譯器將指出錯誤,這無疑會提升程序的健壯性。

例以下面的類MyClass的成員函數getCount(): 1 2 3 4 5

class MyClass { int member ; public: int getCount ( ) const; };

這裏,在函數定義頭後面加上的 const 表示這個函數是一個「只讀函數」,函數不能改變類對象的狀態,不能改變對象的成員變量的值。如在函數體中不能這麼寫: 1 2 3 4

classname :: getCount( ) { member =4 ; return member; }

編譯器將指出getCount 函數中的錯誤,由於試圖修改數據成員member。一樣,const成員函數也不能在函數中調用其餘非const 的函數。

相關文章
相關標籤/搜索