日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++const用法总结

發(fā)布時間:2023/12/29 c/c++ 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++const用法总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

最近在做那個故障樹分析和推理診斷項目,其中的推理診斷部分是用c++來寫的,畢竟是對火箭的故障分析,甲方突然要求推理結(jié)果的精度要很高,讓使用貝葉斯網(wǎng)絡(luò)。找到幾種方案,覺得intel的PNL文檔比較齊全,應(yīng)該靠譜,暫時還在研究PNL中。扯遠(yuǎn)了。。。

推理這部分出于性能各方面的考慮用到了不少const,但是不能稀里糊涂的用啊,于是找到了一篇好文章。全部看完,可以徹底搞清楚const的用法,如果只想了解某一部分,按紅色標(biāo)題找到對應(yīng)部分看也行。

一、關(guān)于一般常量

聲明或定義的格式如下:

const <類型說明符> <變量名> = <常量或常量表達(dá)式>; [1]

<類型說明符> const <變量名> = <常量或常量表達(dá)式>; [2]

[1][2]的定義是完全等價的。

例如:

整形int(或其他內(nèi)置類型:float,double,char

const int bufSize = 512;

或者

int const bufSize = 512;

因為常量在定義后就不能被修改,所以定義時必須初始化。

bufSize = 128;?? //error:attempt to write to const object

const string cntStr ="hello!"; // ok:initialized

const i, j = 0; // error: i isuninitialized const

const變量默認(rèn)為extern

const 對象默認(rèn)為文件的局部變量。要使const變量能夠在其他的文件中訪問,必須顯式地指定它為extern

例如:

const int bufSize =512;??????? // 作用域只限于定義此變量的文件

extern const int bufSize = 512; //extern用于擴大作用域,作用域為整個源程序(只有extern位于函數(shù)外部時,才可以含有初始化式)

二、關(guān)于數(shù)組及結(jié)構(gòu)體

聲明或定義的格式如下:

const <類型說明符> <數(shù)組名>[<大小>]…… [1]

<類型說明符> const <數(shù)組名>[<大小>]…… [2]

[1][2]的定義是完全等價的。

例如:

整形int(或其他內(nèi)置類型:float,double,char

const int cntIntArr[] = {1,2,3,4,5};

或者

int const cntIntArr[] = {1,2,3,4,5};

struct SI

{

??? int i1;

??? int i2;

};

const SI s[] = {{1,2},{3,4}};

// 上面的兩個const都是變量集合,編譯器會為其分配內(nèi)存,所以不能在編譯期間使用其中的值(例如:int temp[cntIntArr[2]]這樣的話編譯器會報告不能找到常量表達(dá)式)

三、關(guān)于引用

聲明或定義的格式如下:

const <類型說明符> &<變量名> = …… [1]

<類型說明符> const &<變量名> = …… [2]

[1][2]的定義是完全等價的。

例如:

const int i = 128;

const int &r = i;(或者 int const &r = i;

const 引用就是指向const對象的引用。

普通引用不能綁定到const對象,但const引用可以綁定到非const對象。

const int ii = 456;

int &rii = ii; // error

int jj = 123;

const int &rjj = jj; // ok

const引用只能綁定到與該引用同類型的對象。

const 引用則可以綁定到不同但相關(guān)的類型的對象或綁定到右值。

例如:

1.const int &r =100;???? // 綁定到字面值常量

2.int i = 50;

const int &r2 = r + i; // 引用r綁定到右值

3.double dVal = 3.1415;

const int &ri = dVal;?? //整型引用綁定到double類型

編譯器會把以上代碼轉(zhuǎn)換成如下形式的編碼:

int temp =dVal;????? // create temporary int from double

const int &ri = temp; // bind ri tothat temporary

四、關(guān)于指針

1.指向const 對象的指針(指針?biāo)赶虻膬?nèi)容為常量)

聲明或定義的格式如下(定義時可以不初始化):

const <類型說明符> *<變量名> …… [1]

<類型說明符> const *<變量名> …… [2]

[1][2]的定義是完全等價的。

例如:

const int i = 100;

const int *cptr = &i;

或者

int const *cptr = &i; [cptr 是指向int類型的const對象的指針]

允許把非const對象的地址賦給指向const對象的指針,例如:

double dVal =3.14;????????? // dVal is adouble; its value can be change

const double *cdptr = &dVal; //ok;but can't change dVal through cdptr

不能使用指向const對象的指針修改基礎(chǔ)對象。然而如果該指針指向的是一個沒const對象(如cdptr),可用其他方法修改其所指向的對象。

如何將一個const對象合法地賦給一個普通指針???

例如:

const double dVal = 3.14;

double *ptr = &dVal; // error

double *ptr =?const_cast<double*>(&dVal);

// ok:?const_castC++中標(biāo)準(zhǔn)的強制轉(zhuǎn)換,C語言使用:double *ptr?=?(double*)&dVal;

2.const 指針(指針本身為常量)

聲明或定義的格式如下(定義時必須初始化):

<類型說明符> *const <變量名> = ……

例如:

int errNumb = 0;

int iVal = 10;

int *const curErr = &errNumb;[curErr 是指向int 型對象的const指針]

指針的指向不能被修改。

curErr = &iVal; // error: curErr isconst

指針?biāo)赶虻幕A(chǔ)對象可以修改。

*curErr = 1; // ok:reset value of theobject(errNumb) which curErr is bind

3.指向const 對象的const 指針(指針本身和指向的內(nèi)容均為常量)

聲明或定義的格式如下(定義時必須初始化):

const <類型說明符> *const <變量名> = ……

例如:

const double pi = 3.14159;

const double dVal = 3.14;

const double *const pi_ptr = &pi;[pi_ptr是指向double類型的const對象的const指針]

指針的指向不能被修改。

pi_ptr = &dVal; // error: pi_ptr isconst

指針?biāo)赶虻幕A(chǔ)對象也不能被修改。

*pi_ptr = dVal; // error: pi is const

五、關(guān)于一般函數(shù)

1.修飾函數(shù)的參數(shù)

class A;

void func1(const int i); // i不能被修改

void func3?(const A&rA);??????? // rA所引用的對象不能被修改

void func2?(const char *pstr); // pstr所指向的內(nèi)容不能被修改

2.修飾函數(shù)的返回值

返回值:const int func1(); //?此處返回int類型的const值,意思指返回的原函數(shù)里的變量的初值不能被修改,但是函數(shù)按值返回的這個變量被制成副本,能不能被修改就沒有了意義,它可以被賦給任何的const或非const類型變量,完全不需要加上這個const關(guān)鍵字。

[*注意*]但這只對于內(nèi)部類型而言(因為內(nèi)部類型返回的肯定是一個值,而不會返回一個變量,不會作為左值使用,否則編譯器會報錯),對于用戶自定義類型,返回值是常量是非常重要的(后面在類里面會談到)。

返回引用:const int &func2(); //注意千萬不要返回局部對象的引用,否則會報運行時錯誤:因為一旦函數(shù)結(jié)束,局部對象被釋放,函數(shù)返回值指向了一個對程序來說不再有效的內(nèi)存空間。

返回指針:const int *func3(); //注意千萬不要返回指向局部對象的指針,因為一旦函數(shù)結(jié)束,局部對象被釋放,返回的指針變成了指向一個不再存在的對象的懸垂指針。

六、關(guān)于類

class A

{

public:

??? void func();

??? void func() const;

??? const Aoperator+(const A &) const;

private:

??? int num1;

??? mutable int num2;

??? const size_t size;

};

1.修飾成員變量

const size_t size; // 對于const的成員變量,[1]必須在構(gòu)造函數(shù)里面進(jìn)行初始化;[2]只能通過初始化成員列表來初始化;[3]試圖在構(gòu)造函數(shù)體內(nèi)對const成員變量進(jìn)行初始化會引起編譯錯誤。

例如:

A::A(size_t sz):size(sz) // ok:使用初始化成員列表來初始化

{

}

A::A(size_t sz)

2.修飾類成員函數(shù)

void func() const; // const成員函數(shù)中不允許對數(shù)據(jù)成員進(jìn)行修改,如果修改,編譯器將報錯。如果某成員函數(shù)不需要對數(shù)據(jù)成員進(jìn)行修改,最好將其聲明為const成員函數(shù),這將大大提高程序的健壯性。

const 為函數(shù)重載提供了一個參考

class A

{

public:

??? voidfunc();??????? // [1]:一個函數(shù)

??? void func() const; //[2]:上一個函數(shù)[1]的重載

??? ……

};

A a(10);

a.func(); // 調(diào)用函數(shù)[1]

const A b(100);

b.func(); // 調(diào)用函數(shù)[2]

如何在const成員函數(shù)中對成員變量進(jìn)行修改???

下面提供幾種方式(只提倡使用第一種,其他方式不建議使用)

(1)標(biāo)準(zhǔn)方式:mutable

class A

{

public:

??? A::A(inti):m_data(i){}

??? void SetValue(int i){m_data = i; }

private:

??? mutable int m_data;// 這里處理

};

(2)強制轉(zhuǎn)換:static_cast

class A

{

public:

??? A::A(inti):m_data(i){}

??? void SetValue(int i)

??? {static_cast<int>(m_data) = i; } //這里處理

private:

??? int m_data;

};

(3)強制轉(zhuǎn)換:const_cast

class A

{

public:

??? A::A(inti):m_data(i){}

??? void SetValue(int i)

??? { const_cast<A*>(this)->m_data= i; } //這里處理

private:

??? int m_data;

};

(4)使用指針:int *

class A

{

public:

??? A::A(inti):m_data(i){}

??? void SetValue(int i)

??? { *m_data = i; } // 這里處理

private:

??? int *m_data;

};

(5)未定義的處理方式

class A

{

public:

??? A::A(inti):m_data(i){}

??? void SetValue(int i)

??? { int *p =(int*)&m_data; *p = i } //這里處理

private:

??? int m_data;

};

注意:這里雖然說可以修改,但結(jié)果是未定義的,避免使用!

3.修飾類對象

const A a; //?類對象a只能調(diào)用const成員函數(shù),否則編譯器報錯。

4.修飾類成員函數(shù)的返回值

const A operator+(const A &) const;//前一個const用來修飾重載函數(shù)operator+的返回值,可防止返回值作為左值進(jìn)行賦值操作。

例如:

A a;

A b;

A c;

a + b = c; // errro: 如果在沒有const修飾返回值的情況下,編譯器不會報錯。

七、使用const的一些建議
???
1.要大膽的使用const,這將給你帶來無盡的益處,但前提是你必須搞清楚原委;

2.要避免最一般的賦值操作錯誤,如將const變量賦值,具體可見思考題;

3.在參數(shù)中使用const應(yīng)該使用引用或指針,而不是一般的對象實例,原因同上;

4.const在成員函數(shù)中的三種用法(參數(shù)、返回值、函數(shù))要很好的使用;

5.不要輕易的將函數(shù)的返回值類型定為const
6.
除了重載操作符外一般不要將返回值類型定為對某個對象的const引用;

八、cons有什么主要的作用?
1.
可以定義const常量,具有不可變性。
例如:

const int Max=100;
int Array[Max];


2.便于進(jìn)行類型檢查,使編譯器對處理內(nèi)容有更多了解,消除了一些隱患。

例如:

void f(const int i) { .........}
編譯器就會知道i是一個常量,不允許修改;


3.可以避免意義模糊的數(shù)字出現(xiàn),同樣可以很方便地進(jìn)行參數(shù)的調(diào)整和修改。
同宏定義一樣,可以做到不變則已,一變都變!如(1)中,如果想修改Max的內(nèi)容,只需要:const int Max=you want;即可!


4.可以保護(hù)被修飾的東西,防止意外的修改,增強程序的健壯性。
還是上面的例子,如果在函數(shù)體內(nèi)修改了i,編譯器就會報錯;
例如:?
void f(const int i) { i=10;//error! }


5.為函數(shù)重載提供了一個參考。
class A
{
???? ......
??? void f(int i)??????{......}?
file://個函數(shù)
??? void f(int i) const {......}?
file://一個函數(shù)的重載
??? ......
};


6.可以節(jié)省空間,避免不必要的內(nèi)存分配。
例如:
#define PI 3.14159?????????
file://量宏
const doulbe Pi=3.14159;?
file://時并未將Pi放入ROM
......
doublei=Pi;???????????????
file://時為Pi分配內(nèi)存,以后不再分配!
doubleI=PI;???????????????
file://譯期間進(jìn)行宏替換,分配內(nèi)存
doublej=Pi;???????????????
file://有內(nèi)存分配
doubleJ=PI;???????????????
file://進(jìn)行宏替換,又一次分配內(nèi)存!

const定義常量從匯編的角度來看,只是給出了對應(yīng)的內(nèi)存地址,而不是象#define一樣給出的是立即數(shù),所以,const定義的常量在程序運行過程中只有一份拷貝,而#define定義的常量在內(nèi)存中有若干個拷貝。


7.提高了效率。
編譯器通常不為普通const常量分配存儲空間,而是將它們保存在符號表中,這使得它成為一個編譯期間的常量,沒有了存儲與讀內(nèi)存的操作,使得它的效率也很高。

{

????size = sz; //error:試圖在構(gòu)造函數(shù)體內(nèi)對const成員變量進(jìn)行初始化

}

總結(jié)

以上是生活随笔為你收集整理的C++const用法总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。