const用法及與constexpr區別總結


1、用const修飾函數的參數

  1. 參數是值傳遞

    由於函數將自動產生臨時變量復制該參數,該參數無需保護,沒必要用const

  2. 參數是指針傳遞或者引用傳遞

    const修飾的指針或引用所指向的值不可變。如果該參數只是起“被讀取”的作用,最好用const修飾保護。

對於復合數據類型,最好使用引用傳遞,因為值傳遞的過程中要進行臨時對象的構造,復制,析構,這些都會造成時間和空間的浪費。

class list {
    string name;
    public:
    	void show(const list& l) {
            cout << name;
        }
}

2、用const修飾函數的返回值

如果函數的返回值用const修飾,接受這個返回值的變量也只能用const修飾。

const int sum(int a, int b) {return a+b;}

int s = sum(1,1); //error
const s = sum(1,1); //編譯通過

3、const 成員函數

任何不會修改數據成員的函數都應該聲明為const 類型。如果在編寫const 成員函數時,不慎修改了數據成員,或者調用了其它非const 成員函數,編譯器將指出錯誤,這無疑會提高程序的健壯性。

class list {
    string name;
    public:
    	void show(list& l) const {
            cout << name;
        }
}

4 、const對象

const修飾的對象只能訪問const函數和const成員變量

class list {
    string name;
    public:
    	void show(list& l) const {
            cout << name;
        }
    	void show2(list& l) {
            cout << name;
        }
}

const list l;
l.show2(); //error
l.show(); //編譯通過

5 、與constexpr區別

  1. 對於修飾Object來說

    • const並未區分出編譯期常量(編譯時就可以確定的常量表達式)和運行期常量
    • constexpr限定在編譯期常量,也就是說,編譯器看見constexpr就可以放心的對常量進行編譯期的優化了。
  2. 對於修飾函數來說

    • constexpr修飾的函數,返回值不一定是編譯期常量

      #include <iostream>
      #include <array>
      using namespace std;
      
      constexpr int foo(int i)
      {
          return i + 5;
      }
      
      int main()
      {
          int i = 10;
          std::array<int, foo(5)> arr; // OK
          
          foo(i); // Call is Ok
          
          // But...
          std::array<int, foo(i)> arr1; // Error
         
      }
      

所以,對於constexpr需要兩方面看待。

constexpr修飾的函數,簡單的來說,如果其傳入的參數可以在編譯時期計算出來,那么這個函數就會產生編譯時期的值。但是,傳入的參數如果不能在編譯時期計算出來,那么constexpr修飾的函數就和普通函數一樣了。不過,我們不必因此而寫兩個版本,所以如果函數體適用於constexpr函數的條件,可以盡量加上constexpr

而檢測constexpr函數是否產生編譯時期值的方法很簡單,就是利用std::array需要編譯期常值才能編譯通過的小技巧。這樣的話,即可檢測你所寫的函數是否真的產生編譯期常值了。

6、指向常量的指針(pointer to const)、常量指針指針(const pointer) 與 constexpr指針

  • 指向常量的指針,又叫底層指針

    • 作用:不能通過指針修改值,無論指向的值是否是const, 指針本身可以改變指向。

      int a =1;
      const int b = 1;
      const int* p;
      p = &a;
      *p = 2;//錯誤
      p = &b;
      *p = 2; //錯誤
      
  • 常量指針,又叫頂層指針

    • 作用:不能修改指針的指向,指針本身是常量,所以必須在聲明時初始化。

      int a = 1;
      int b = 1;
      int* const p = &a;
      p = &b; //報錯
      
  • constexpr指針

    • 作用和常量指針(頂層指針)一樣

6.5、類型別名與常量指針

typedef int* ip;
int a = 1;
const ip p;  //等價於 int* const p;  也就是頂層指針,頂層指針必須初始化,所以這句是會報錯的
const ip p = &a; //正確

7、const引用

int const& a;const int& a; 作用一樣,可以不加區分。

參考:https://www.zhihu.com/question/35614219/answer/63798713

https://www.jianshu.com/p/34a2a79ea947

《C++ primer》2.4節


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM