神奇的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;
然後編譯一直沒報錯,哈哈,一時之間,想不太懂,後來才想明白了。
因為,對于這個語句,編譯器先執行++,就是說它的位址先改變了一下,然後輸出了所指向的值,故也是正确的