C++ const用法小結

C++const 關鍵字小結

constconstant的縮寫,本意是不變的,不易改變的意思。html

const 在C++中是用來修飾內置類型變量,自定義對象,成員函數,返回值,函數參數ios

short conclusion

// for variable
const int a = 8;
int *p = (int *)&a;
*p =7;      // wrong, it's unpredictable

// for pointer, 左定值,右定向
int a = 8;
const int *p = &a;
*p = 7;     // wrong

int * const p2 = &a;
int b = 10;
p2 = &b;    // wrong

// for func param
class A {};

void func(const A *a){}     // equal to void func(const A& a){}, improve performance for copy constructor comparing to void func(A a)

void func(A * const a){}    // equal to void func(A& a){}

// for class method, indicate 'the method can't modify the instance data', (mutable修飾的變量除外)
// 不能調用非const成員函數
class B{
    private:
        int count;
    public:
        int GetCount() const {
            count ++; // wrong
            return count;
        }
}

// for return value, no practical value

1、const修飾普通類型的變量。

以下:函數

const int  a = 7; 

int  b = a; //it's right

a = 8;       // it's wrong,

a被定義爲一個常量,而且能夠將a賦值給b,可是不能給a再次賦值。對一個常量賦值是違法的事情,由於a被編譯器認爲是一個常量,其值不容許修改優化

接着看以下的操做:this

#include<iostream>
using namespace std;

int main(void)
{

    const int  a = 7;
    int  *p = (int*)&a;

    *p = 8;

    cout<<a;
    system("pause");
    return 0;
}

對於const變量a,咱們取變量的地址並轉換賦值給 指向int的指針,而後利用*p = 8;從新對變量a地址內的值賦值,而後輸出查看a的值。spa

從下面的調試窗口看到a的值被改變爲8,可是輸出的結果仍然是7。3d

img

img

從結果中咱們能夠看到,編譯器而後認爲a的值爲一開始定義的7,因此對const a的操做就會產生上面的狀況。因此千萬不要輕易對const變量設法賦值,這會產生意想不到的行爲。指針

若是不想讓編譯器察覺到上面到對const的操做,咱們能夠在const前面加上volatile關鍵字調試

Volatile關鍵字跟const對應相反,是易變的,容易改變的意思。因此不會被編譯器優化,編譯器也就不會改變對a變量的操做。code

#include<iostream>

using namespace std;

int main(void)
{

    volatile const int  a = 7;
    int  *p = (int*)&a;

    *p = 8;

    cout<<a;

    system("pause");
    return 0;
}

輸出結果如咱們指望的是8

img

2、const 修飾指針變量。

const 修飾指針變量有如下三種狀況。

  • A:const 修飾指針指向的內容,則內容爲不可變量。
  • B:const 修飾指針,則指針爲不可變量。
  • C:const 修飾指針和指針指向的內容,則指針和指針指向的內容都爲不可變量。

對於A:

const int *p = 8;

則指針指向的內容8不可改變。簡稱左定值,由於const位於*號的左邊

對於B:

int a = 8;
 int* const p = &a;

 *p = 9; //it’s right

 int  b = 7;
 p = &b; //it’s wrong

對於const指針p其指向的內存地址不可以被改變,但其內容能夠改變。簡稱,右定向。由於const位於*號的右邊

對於C:

則是A和B的合併,

int a = 8;
const int * const  p = &a;

這時,const p的指向的內容和指向的內存地址都已固定,不可改變。

const修飾指針Conclusion

對於A,B,C三種狀況,根據const位於*號的位置不一樣,我總結三句話便於記憶的話,

左定值,右定向,const修飾不變量

3、const in function參數傳遞

對於const修飾函數參數能夠分爲三種狀況。

值傳遞的const修飾傳遞

A:值傳遞的const修飾傳遞,通常這種狀況不須要const修飾,由於函數會自動產生臨時變量複製實參值

#include<iostream>

using namespace std;

void Cpf(const int a)
{
    cout<<a; 
    // ++a;  it's wrong, a can't is changed
}

int main(void)
{
    Cpf(8);

    system("pause"); 
    return 0;
}

const參數爲指針

B:當const參數爲指針時,能夠防止指針被意外篡改。

#include<iostream>

using namespace std;

void Cpf(int *const a) 
{ 
    cout<<*a<<" ";
    *a = 9;
}

int main(void)
{ 
    int a = 8; 
    Cpf(&a);

    cout<<a; // a is 9 
    system("pause");
    return 0;
}

self definded type, const reference

C:自定義類型的參數傳遞,須要臨時對象複製參數,對於臨時對象的構造,須要調用構造函數,比較浪費時間,所以咱們採起const外加引用傳遞的方法。

而且對於通常的int ,double等內置類型,咱們不採用引用的傳遞方式。

#include<iostream>

using namespace std;

class Test 
{ 
public: 
    Test(){} 

    Test(int _m):_cm(_m){}

    int get_cm() const 
    {
       return _cm;
    }

private:
    int _cm;
};


void Cmf(const Test& _tt)
{
    cout<<_tt.get_cm(); 
}

int main(void) 
{
    Test t(8);

    Cmf(t);

    system("pause");
    return 0;
}

結果輸出 8

四 const修飾函數的返回值

Const修飾返回值分三種狀況。

A:const修飾內置類型的返回值,修飾與不修飾返回值做用同樣。

#include<iostream>

using namespace std;

const int Cmf()
{ 
    return 1; 
}

int Cpf() 
{ 
    return 0;
}

int main(void) 
{
    int _m = Cmf(); 
    int _n = Cpf();

    cout<<_m<<" "<<_n;
    system("pause"); 
    return 0;
}

B:const 修飾自定義類型的做爲返回值,此時返回的值不能做爲左值使用,既不能被賦值,也不能被修改。

C: const 修飾返回的指針或者引用,是否返回一個指向const的指針,取決於咱們想讓用戶幹什麼。

5、const修飾類成員函數.

const 修飾類成員函數,其目的是防止成員函數修改被調用對象的值,若是咱們不想修改一個調用對象的值,全部的成員函數都應當聲明爲const成員函數。注意:const關鍵字不能與static關鍵字同時使用,由於static關鍵字修飾靜態成員函數,靜態成員函數不含有this指針,即不能實例化,const成員函數必須具體到某一實例。

下面的get_cm() const;函數用到了const成員函數

#include<iostream>

using namespace std;

class Test
{
public:
    Test(){}
    Test(int _m):_cm(_m){}

    int get_cm()const
    {
       return _cm;
    }

private:
    int _cm;

};

void Cmf(const Test& _tt)
{
    cout<<_tt.get_cm();
}

int main(void)
{
    Test t(8);
    Cmf(t);

    system("pause");
    return 0;
}

若是get_cm()去掉const修飾,則Cmf傳遞的const _tt即便沒有改變對象的值,編譯器也認爲函數會改變對象的值,因此咱們儘可能按照要求將全部的不須要改變對象內容的函數都做爲const成員函數。

若是有個成員函數想修改對象中的某一個成員怎麼辦?這時咱們可使用mutable關鍵字修飾這個成員,mutable的意思也是易變的,容易改變的意思,被mutable關鍵字修飾的成員能夠處於不斷變化中,以下面的例子。

#include<iostream>
using namespace std;

class Test
{
public:
    Test(int _m,int _t):_cm(_m),_ct(_t){}
    void Kf() const
    {
        ++_cm; //it's wrong
        ++_ct; //it's right
    }
private:
    int _cm;
    mutable int _ct;
};

int main(void)
{
    Test t(8,7);
    return 0;
}

這裏咱們在Kf()const中經過++_ct;修改_ct的值,可是經過++_cm修改_cm則會報錯。由於++_cm沒有用mutable修飾

轉載:

C++ const用法 儘量使用const http://www.javashuo.com/article/p-bqwkndqd-cd.html

C++const 關鍵字小結 https://www.cnblogs.com/Forever-Kenlen-Ja/p/3776991.html

相關文章
相關標籤/搜索