c++ constexpr用法


測試環境:windows10 + gcc8.1

1、constexpr產生背景

c++11以后,為了保證寫出的代碼比以往任何時候的執行效率都要好而進行了許多改善。其中,這種改善之一就是生成常量表達式,允許程序利用編譯時的計算能力。常量表達式主要是允許一些計算發生在編譯時期,而不是運行時期。這是一個很進步的優化:假如有些事情可以在編譯時計算,它將只計算一次,而不是在運行時每一次都進行計算。需要計算一個編譯時已知的常量,比如特定的sin或者cos值,確實可以使用庫函數sin和cos,但那樣做是必須花費運行時的開銷。此時可以使用constexpr創建一個編譯時的函數,它將在編譯時期計算出你需要的數值,而在用戶的電腦上將無需做這些工作。

2、constexpr用法

為了使函數獲取編譯時計算的能力,必須給該函數指定constexpr關鍵字。

constexpr int multiply(int x,int y)
{
    return x* y;
}
//將在編譯時期計算
const int var = multiply(10,10);

除了編譯時計算性能的優化,congtexpr的另外一個優勢是:允許函數被應用到以前調用宏的所有場合。例如:想要計算數組size的函數,size是10的倍數。如果不用constexpr,則需要創建一個宏或者模板,因為我們不能用函數的返回值去聲明數組的大小。但是我們可以調用一個constexpr函數去聲明一個數組。

constexpr int getDefaultArraySize(int value)
{
    return value*10;
}
int my_array[getDefaultArraySize(3)];

3、constexpr使用限制

c++11中的constexpr指定的函數返回值和參數都必須保證是字面值,而且必須有且只有一行代碼(return代碼)。所以通常只能通過return 三目運算符+遞歸來計算返回的字面值。

constexpr int factorial (int n)
{
    return n > 0 ? n * factorial( n - 1 ) : 1;
}

c++14中則只要保證返回值和參數是字面值就行,函數體中可以加入更多的語句,實現了更靈活的計算。

// C++14
constexpr int factorial2(int n)
{
    int result = 1;
    for (int i = 1; i <= n; ++i)
        result *= i;
    return result;
}

c++17中lambda表達式可以被聲明為constexpr。對於一個lambda而言,只要被捕獲的變量是字面量類型(lieteral type),那么整個lambda也將表現為字面量類型。

//顯示聲明為constexpr類型
template <typename T>
constexpr auto addTo(T i){
    return[i](auto j){return i+j;};
}
constexpr auto add5 = addTo(5);

當一個閉包再constexpr環境下被使用時,當它滿足了constexpr的條件,則無論它有沒有被顯示地聲明為constexpr,它仍然是constexpr的。

 //這里沒有顯式聲明為constexpr,但依然可以表現為constexpr
 auto answer = [](int n)
 {
   return 32 + n;
 };
 //在一個constexpr環境中被使用
 constexpr int response = answer(10);

在c++17 中contexpr if 讓以前理應被寫在一起的代碼,卻在c++17前都沒法被寫在一起的情況得到了改善。傳統的if-else語句是在執行期進行條件判斷與選擇的,因而在泛型編程中,無法使用if-else語句進行判斷。在c++17中,我們可以在編譯期對傳統的條件語句做出相應判斷,可以忽略那些完全沒有被進入的語句。

注意,在老的標准中,計算使用了if,另一個分支也仍然會被編譯,但在c++17中,如果使用if constexpr來替代if,編譯器甚至會把編譯無效條件這個過程忽略掉。

constexpr對STL庫標准做出的改進:

以前在標准庫中,有許多類型和函數都缺乏了constexpr的特性,這些問題在C++17中都相應做了改進。最著名的就是std::array以及用於范圍獲取的std::begin()和std::end()。

 


免責聲明!

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



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