天天看點

淺談C++中的Const

神奇的const,我們研究C、C++經常碰到的一個問題(const的簡單用法,不變的函數參數,const int *p,int * const p)這些都是我們所必須要消滅的一點東西。

C++在變量聲明使用限定符const

Const用法主要是防止定義的對象再次被修改,定義對象變量是要初始化變量,簡單地來講,就是它把一個對象轉化成了一個變量

1,Const與define

在C中,可以使用#define來定義符号常量,例如: 

#define PI 3.14159

在C++中,提供了一種更靈活, 更安全的方式來定義關鍵字const來定義符号常量,例如:

const float PI 3.14159;              //PI是一個常量

const  int   x;                  //error: 定義常量是應指派,否則出錯

void      f(){

          PI =40;              //error :不能修改常量的值

}

          簡單地說:用define定義常量後面必須沒有分号,并且不要求指出其具體的類型,const定義常量相當于一條語句,後面有分号,并且要求指出其具體的類型(如果沒有,C++編譯器會預設其為int),還要同時給常量指派。

(請大家注意:在C++中,  

const int a;

int const a;

上面兩條語句的實質是一樣的,沒有差別,完全等價,至于采用哪種寫法,完全根據個人習慣)

2, const  int  * p與int  *  const p與int const * p

#include <stdio.h>

int main(){
	int a=100, b = 200;
	
	const int *p = &a;
	int *const q = &b;
	printf("a = %d, *p = %d\n", a, *p);
	printf("b = %d, *q = %d\n", b, *q);
	
	/*不可使用*p間接的更改變量a的值
	*p = b;
	*/
	/*但是可以将p指針指向另一變量的位址*/
	p = &b;
	printf("*p = %d\n", *p);
	
	
	/*不可更改q指針指向另一變量的位址
	q = &a;
	*/
    /*但可以使用q指針間接更改變量b的值*/
	*q = 123;
	printf("*q = %d\n", q);
	return  0; 
	
}
           

const  int *p = &a;

const修飾的是整個*p,是以*p是個常量,是不能被指派的。

p前面并沒有用const修飾,是以p是指針變量,故可以被指派重新指向另一個記憶體

int  const *p 與 const  int  *p完全相同,其都是修飾整個*p

int * const q = &b;

q因為有了const修飾,是以q值是不可修改的。

整個*q的前面沒有const的修飾,也就是說,*q是變量,是以可以通過*q來修改它所指向記憶體的值

但是,但是,但是,我們切不可把常量指針指派給非常量指針,反過來可以

const  int  * p1;

int * p2;

p1 = p2;                   //ok

p2 = p1;                   //error (如果這樣的話,會不經意間改變p2所指向的值,來間接的改變p1所指向的值,導緻錯)

p2 = (int *)p1;          //ok,(非要轉化的話,我們可以通過強制類型轉化啊)

3,const int * const p 與int const *p const與int const *const p;

上面這幾種情況,我們一定要注意const各自的位置

對于第一個和第三個他們其實是一樣的,是以不用糾結,但是對于第二個(這個寫法沒有)

#include <stdio.h>

int main(){
	int a=100, b = 200;
	
	const int * const p = &a;
	//p = &b;       
	//*p = b;
	return  0; 
}
           

對于const int * const p  = &a,首先通過第一個const明白*p是常量,

故不可以給: *p指派,                      如:*p = 200;

通過第二個const明白p是常量

故不可以給:p指向另一變量                  如: p = &b;

4, const修飾函數

當一個指針送給一個函數後,函數可能修改該指針所指向的變量,然而,如果指針在參數說明段用const修飾,函數就無法修改指針所指向的内容了,

實際上,在C标準庫中許多的函數在其參數說明中都使用了const, 

basic_string(const basic_string& __str, size_type __pos,
		   size_type __n, const _Alloc& __a);
           

上面是在dev-c++中的string源檔案中找見的,有興趣的可以去看看

#include <iostream>
using namespace std;

void print(const float *salary){
	*salary = *salary +1;          //直接修改了一個常量,編譯肯定出錯
	cout<<*salary<<endl;
}

int main(){
	float mysalary;
	cin>>mysalary;
	print(&mysalary);
	
	return 0;
}
           

對于上面print函數而言,它的參數是:const   float *salary,就意味着*salary不可被随意更改,上面的程式内部更改了這個常量,故編譯一定出錯

當時一時興起,将其改為:

*salary++;

cout<<*salary<<endl;

然後編譯一直沒報錯,哈哈,一時之間,想不太懂,後來才想明白了。

因為,對于這個語句,編譯器先執行++,就是說它的位址先改變了一下,然後輸出了所指向的值,故也是正确的