const主要是為了程序的健壯型,減少程序出錯.
最基本的用法:
const int a=100; b的內容不變,b只能是100也就是聲明一個int類型的常量(#define b =100)
int const b=100; //和上面作用一樣
const指針和引用一般用在函數的參數中
int* m = &a; //出錯,常量只能用常指針
int c= 1;const int*pc = &c;//常指針可指向常量
const int* pa = &a; //指針指向的內容為常量(就是b的值不變)
int const *a = &b; //指針指向的內容為常量(就是b的值不變)*p=3//error
int* const a = &b; //指針為常量,不能更改指針了如 a++但可以改值*p=3;
從這可以看出const放在*左側修飾的是指針的內容,const放在*右側修飾的是指針
本身.
const引用的用法和指針一樣
int const & a=b; 和指針一樣
const int& a=b; 和指針一樣
但沒有 int& const a=b 的用法因為引用不能做移位運算,但只是出個warning
const int* const a = &b; //綜合應用,一般用來傳遞多維的數組
類如:char* init[] = {"Paris","in the","Spring"};
void fun(const int* const a){}
fun(init)//保護參數不被修改
int A(int)const; //是常函數,只能用在類中,調用它的對象不能改改變成員值
const int A(); //返回的是常量,所以必須這么調用 cosnt int a=A();
int A(const int); //參數不能改值,可用在任意函數
int A(const int*);
....
int height() const;//常函數只能由常函數調用
int max(int,int) const;
int Max = max(height(),height());
const int* pHeap = new int;
delete pHeap;
p = NULL;//出錯
我的解決辦法是強制類型轉換
const int* pHeap = new int(1);
delete (int*)pHeap;
pHeap = NULL;
一、const 和引用聯合使用的時候要注意
const int a = 1;
const int& ref1 = a;
const int& ref2 = 1;
ref1 和 ref2 都是正確的,但是他們引用的內容和一般的引用不同
對 const int& ref1 = a; 而言,其實這個 ref1 已經和 a 沒有任何關系了
ref1 實際上是對一個臨時量的引用。同理 const int& ref2 = 1; 也是對
一個臨時量做的引用。當引用臨時量是 C++ 的隱式類型轉換可以起作用。
臨時量的生存期和引用量的生存期相同。
二、強傳const對象可能導致無定義行為
對于優化做的比較好的編譯器,代碼 const int i = 1;
當后面用到變量 i 的時候,編譯器會優化掉對 i 的存取,而直接使用立即數 1
const int i = 1;
*(const_cast<int*>(&i)) = 2;
cout << *(int*)&i << endl;
cout << i << endl;
所以,對 const 對象做 const_cast 可能導致無定義行為
目前我就遇到這些問題,那位還有補充的嗎
能不能把自己的經驗也談談。大家交流交流
這個就是我在調錯時發現的
int height() const;//常函數只能由常函數調用
int max(int,int) const;
int Max = max(height(),height());
Thinking again in C++(一)常量性原理 cphj(原作)
有些地方很受啟發
1.不能將const修飾的任何對象、引用和指針作為賦值表達式的左值。
const int cx=100;
const int & rcx=cx;
const int * pcx=&cx;
cx=200; //error
rcx=200; //error
*pcx=200; //error
2.const類型的對象不能直接被non-const類型的別名所引用。
(1)不能將const類型的對象傳遞給non-const類型的引用。
const int cx=100;
int & rx=cx; //error
(2)不能將const類型的實參傳遞給形參為non-const類型引用的函數。
void f(int a)
{
}
void g(int & ra)
{
}
const int cx=100;
f(cx); //ok
g(cx); //error
(3)不能將const類型的對象作為non-const類型引用的函數返回值。
int & f(const int & rca)
{
return rca; //error
}
int x=100;
f(x);
3.可以使用const類型別名引用non-const對象。此時通過const引用不能修改對象,但對象可以通過non-const引用被修改。
int x=100;
int & rx=x;
const int & rcx=x; //ok
x=200;
rx=200;
rcx=200; //error
4.指針的屬性有兩個:指針的類型和指針本身的常量性。其中,指向const對象與指向non-const對象,是不同的指針類型。
int x=100;
const int * pcx=&x; //[1]
int * px=&x; //[2]
int y=100;
int * const cpy=&y; //[3]
int * py=&y; //[4]
[1][2]兩個指針的類型不同;[3][4]兩個指針的常量性不同。
對象與指向對象的指針的規則類似于對象與引用。即,const類型的對象不能直接被non-const類型的指針所指示(同2);可以使用const類型的指針指向non-const對象(同3)。
5.可以將相同類型(包括常量性)的const指針值賦給non-const指針。
int x=100;
int * px;
const int * pcx=&x;
px=pcx; //error
int * const cpx=&x;
px=cpx; //ok
6.若函數的返回值為內建類型或是指針,則該返回值自動成為const性質。但自定義類型則為non-const性質。
int f() //相當于返回const int
{
return 100;
}
int * g(int & ra) //相當于返回int * const
{
return &ra;
}
class CTest
{
int n;
public:
CTest(int n){this->n=n;}
};
CTest h() //返回的就是CTest
{
return CTest(200);
}
f()=200; //error
int x=100;
int y=200;
int * px=&x;
g(y)=px; //error
*g(y)=x; //ok,從這點可以看出g()返回的不是const int *
CTest t(100);
h()=t; //ok,但卻是完全錯誤的、危險的做法
//所以h()的正確寫法是返回const CTest
const int b=100; b的內容不變,b只能是100
int const b=100; b必須為int型,不能為其他類型?
這2句話的意思應該是一樣的吧 , THINKING IN C++是這樣說的
const int a=100; a的內容不變,a只能是100(同樣不能類型轉換)。
int const b=100; b必須為int型,不能為其他類型?(同樣在使用中不能修改)。
所以a和b是一樣的,稱為整型常數,在使用中不能被修改,當然都不能轉為其他類型了。
#include <iostream>
using namespace std;
int main()
{
const int a = 100;
int const b = 100;
a = 100; //這四條語句編譯時都會出現“Cannot modify a const object
b = 100; //in function main()”的錯誤提示,也就是說,任何企圖修改 a = 100.0; //a和b(其實是一樣的)的行為都會出現“災難”,在語法上講就 b = 100.0; //是a和b都不能出現在賦值語句的左邊!
cout<<'\n'<<a<<'\n'<<b<<endl;
return 0;
}
常函數的調用是這樣的:常量對象只能調用常成員函數,非常量對象即可以調常成員函數,也可以調一般成員函數,但當某個函數有const和非const兩個版本時,const對象調const版本,非const對象調非const版本
例:
class A
{
public:
int & GetData(){return data;}
const int & GetData()const {return data;}
private:
int data;
}
A a;
a.GetData();//調用int & GetData(){return data;}
//但如果沒有這個函數,也可以調用const int & GetData()const
const A const_a;
const_a.GetData();//調用const int & GetData()const {return data;}
常函數只能調常函數,也是由于這個原因
算你狠!加兩點
一、const 和引用聯合使用的時候要注意
const int a = 1;
const int& ref1 = a;
const int& ref2 = 1;
ref1 和 ref2 都是正確的,但是他們引用的內容和一般的引用不同
對 const int& ref1 = a; 而言,其實這個 ref1 已經和 a 沒有任何關系了
ref1 實際上是對一個臨時量的引用。同理 const int& ref2 = 1; 也是對
一個臨時量做的引用。當引用臨時量是 C++ 的隱式類型轉換可以起作用。
臨時量的生存期和引用量的生存期相同。
二、強傳const對象可能導致無定義行為
對于優化做的比較好的編譯器,代碼 const int i = 1;
當后面用到變量 i 的時候,編譯器會優化掉對 i 的存取,而直接使用立即數 1
const int i = 1;
*(const_cast<int*>(&i)) = 2;
cout << *(int*)&i << endl;
cout << i << endl;
所以,對 const 對象做 const_cast 可能導致無定義行為
#include <iostream.h>
void fun(char b){cout <<"void"<<endl;}
int fun(int const b){cout <<"int"<<endl;}
int main()
{
fun(1.0);//詳細看看重載函數吧
fun(4); //想一想調用哪一個
return 0;
}
我試了一下,會出錯? vc說:'fun':ambiguous call to overloaded function
補充的好啊,這個一般不會注意的
const int i = 1;
*(const_cast<int*>(&i)) = 2;
cout << *(int*)&i << endl;
cout << i << endl;
這個可真有意思,調試時兩個都是2,可編譯就是2,1了
const的永遠都是const,這樣能更改就不錯了,不然就自相矛盾了
奇怪的是 pi 和 &i地址一樣啊,就像樓上說的這是編譯時的優化
處理
const int i = 1;
int* pi=const_cast<int*>(&i);
*pi=2;
cout << *pi << endl;
cout << i << endl;
那個主要是隱式轉換
你可依次把兩個函數注掉看看調用
#include <iostream.h>
//void fun(char b){cout <<"void"<<endl;}
void fun(int b){cout <<"int"<<endl;}
int main()
{
fun('a');
fun(4);
return 0;
}