const

1. 修飾普通變量

用const修飾的變量是不變的,不能爲其賦值。ios

const int a = 1;
int const a = 1;

2. 修飾指針

若是const位於*的左側,則const就是用來修飾指針所指向的變量,即指針指向爲常量;
若是const位於*的右側,const就是修飾指針自己,即指針自己是常量。
所以,推薦使用int const* p,而不是使用const int* p(雖然二者意義徹底同樣),這樣更容易理解。
int a = 10;
const int* p = &a;            // 指針指向的內容不能變
int const* p = &a;            // 同上
int* const p = &a;            // 指針自己不能變
const int* const p = &a;      // 二者都不能變
int const* const p = &a;      // 同上

3. 修飾引用

如下兩種定義形式在本質上是同樣的:安全

int a = 10;
const int& b = a; // 常引用:不能經過b去修改a的值
int const& b = a;

4. 修飾函數參數

用const修飾函數參數,傳遞過來的參數在函數內不能夠改變。函數

void func (const int& n)
{
    n = 10;// 編譯錯誤
}

5. 修飾函數返回值

用const修飾函數返回值的含義和用const修飾普通變量以及指針的含義基本相同。指針

const int* func() // 返回的指針所指向的內容不能修改
{
    // return p;
}

6. 修飾類成員變量

用const修飾的類成員變量,只能在類的構造函數初始化列表中賦值,不能在類構造函數體內賦值。code

class A
{
public:
    A(int x) : a(x)  // 正確
    {
         //a = x;    // 錯誤
    }

private:
    const int a;
};

問題:類的構造函數初始化列表中賦值和函數體內賦值有啥差異?對象

7. 修飾類成員函數

用const修飾的類成員函數,在該函數體內不能改變該類對象的任何成員變量, 也不能調用類中任何非const成員函數。內存

class A
{
public:
    int& getValue() const
    {
        // a = 10;    // 錯誤
        return a;
    }

private:
    int a;            // 非const成員變量
};

8. 修飾類對象

用const修飾的類對象,該對象內的任何成員變量都不能被修改。
所以不能調用該對象的任何非const成員函數,由於對非const成員函數的調用會有修改爲員變量的企圖。get

class A
{
 public:
    void funcA() {}
    void funcB() const {}
};

int main
{
    const A a;
    a.funcB();    // 能夠
    a.funcA();    // 錯誤

    const A* b = new A();
    b->funcB();    // 能夠
    b->funcA();    // 錯誤
}

9. 在類內重載成員函數

class A
{
public:
    void func() {}
    void func() const {}   // 重載
};

10. const與宏定義的區別

const常量有數據類型,而宏常量沒有數據類型。編譯器能夠對前者進行類型安全檢查,而對後者只進行字符替換,沒有類型安全檢查,而且在字符替換時可能會產生意料不到的錯誤。
const常量從彙編的角度來看,只是給出了對應的內存地址,而不是象#define同樣給出的是當即數,因此,const定義的常量在程序運行過程當中只有一份拷貝,而#define定義的常量在內存中有若干個拷貝。
另外,編譯器一般不爲const常量分配存儲空間,而是將它們保存在符號表中,這使得它成爲一個編譯期間的常量,沒有了存儲與讀內存的操做,使得它的效率也很高。編譯器

#define PI 3.1415926535
const double PI = 3.1415926535;

11. const_cast

const_cast運算符用來修改類型的const或volatile屬性。
1、常量指針被轉化成很是量的指針,而且仍然指向原來的對象;
2、常量引用被轉換成很是量的引用,而且仍然指向原來的對象。io

#include <iostream>
int main()
{
    const int a = 10;
    int* p = const_cast<int*> (&a);
    *p = 20;
    std::cout<<"p的地址: " << &p << "   ";
    std::cout<<"p的內容: " << p << std::endl;
    std::cout<<"*p的地址: " << &(*p) << "   ";
    std::cout << "*p的內容: " << *p << std::endl;    // 20
    std::cout << "a的地址: " << &a << "   ";
    std::cout << "a的內容: " << a << std::endl;     // 10, 緣由見第10部分
    return 0;
}

// 名稱    p                   a                   *p
// 數據    0x7ffeed81eaa8      10                  20
// 地址    0x7ffeed81eaa0      0x7ffeed81eaa8      0x7ffeed81eaa8
相關文章
相關標籤/搜索