C++11/C++14中constexpr的使用案例詳解
常量表達式(const expression)是指值不會改變并且在編譯過程中就能得到計算結(jié)果的表達式。字面值屬于常量表達式,用常量表達式初始化的const對象也是常量表達式。
只要有可能使用constexpr,就使用它。
C++11中constexpr的使用:
constexpr是C++11中添加的一個特性,其主要思想是通過在編譯時而不是運行時進行計算來提高程序的性能,將時間花在編譯上,而在運行時節(jié)省時間(類似于模版元編程)。
C++11規(guī)定,允許將變量聲明為constexpr類型以便由編譯器來驗證變量的值是否是一個常量表達式。聲明為constexpr的變量一定是一個常量,而且必須用常量表達式初始化。
盡管不能使用普通函數(shù)作為constexpr變量的初始值,但C++11標(biāo)準(zhǔn)允許定義一種特殊的constexpr函數(shù)。這種函數(shù)應(yīng)該足夠簡單以使得編譯時就可以計算其結(jié)果,這樣就能用constexpr函數(shù)去初始化constexpr變量了。
一般來說,如果你認(rèn)定變量是一個常量表達式,那就把它聲明成constexpr類型。
所有constexpr對象都是const對象,而并非所有的const對象都是constexpr對象。如果你想讓編譯器提供保證,讓變量擁有一個值,用于要求編譯期常量的語境,那么能達到這個目的的工具是constexpr,而非const。
constexpr函數(shù)是指能用于常量表達式的函數(shù)。定義constexpr函數(shù)的方法與其它函數(shù)類似,不過要遵循幾項約定:函數(shù)的返回類型及所有形參的類型都得是字面值類型,而且函數(shù)體中必須有且只有一條return語句。constexpr函數(shù)或構(gòu)造函數(shù)被隱式地指定為內(nèi)聯(lián)函數(shù)。
constexpr函數(shù)體內(nèi)也可以包含其它語句,只要這些語句在運行時不執(zhí)行任何操作就行。例如,constexpr函數(shù)中可以有空語句、類型別名以及using聲明。
允許constexpr函數(shù)的返回值并非一個常量。constexpr函數(shù)不一定返回常量表達式。
和其它函數(shù)不一樣,內(nèi)聯(lián)函數(shù)和constexpr函數(shù)可以在程序中多次定義。不過,對于某個給定的內(nèi)聯(lián)函數(shù)或者constexpr函數(shù)來說,它的多個定義必須完全一致?;谶@個原因,內(nèi)聯(lián)函數(shù)和constexpr函數(shù)通常定義在頭文件中。
constexpr函數(shù)只能調(diào)用其它constexpr函數(shù),不能調(diào)用簡單函數(shù)(simple function)。constexpr函數(shù)不應(yīng)該是void類型。constexpr函數(shù)中不允許有前綴增量(++i),在C++14中已刪除此限制。
constexpr函數(shù)的理解:
(1).constexpr函數(shù)可以用在要求編譯期常量的語境中。在這樣的語境中,若你傳給一個constexpr函數(shù)的實參值是在編譯期已知的,則結(jié)果也會在編譯期間計算出來。如果任何一個實參值在編譯期未知,則你的代碼將無法通過編譯。
(2).在調(diào)用constexpr函數(shù)時,若傳入的值有一個或多個在編譯期未知,則它的運作方式和普通函數(shù)無異,亦即它也是在運行期執(zhí)行結(jié)果的計算。這意味著,如果函數(shù)執(zhí)行的是同樣的操作,僅僅應(yīng)用的語境一個是要求編譯期常量的,一個是用于所有其它值的話,那就不必寫兩個函數(shù)。constexpr函數(shù)就可以同時滿足所有需求。
constexpr函數(shù)僅限于傳入和返回字面類型(literal type),意思就是這樣的類型能夠持有編譯期可以決議的值。在C++11中,所有的內(nèi)建類型,除了void,都符合這個條件。但是用戶自定義類型同樣可能也是字面類型,因為它的構(gòu)造函數(shù)和其它成員函數(shù)可能也是constexpr函數(shù)。
在C++11中,constexpr函數(shù)都隱式地被聲明為const。
以下為測試代碼:
namespace { // constexpr function: constexpr函數(shù)被隱式地指定為內(nèi)聯(lián)函數(shù) constexpr int new_sz() { return 42; } constexpr size_t scale(size_t cnt) { return new_sz() * cnt; } constexpr int product(int x, int y) { return (x * y); } // pow前面寫的那個constexpr并不表明pow要返回一個const值,它表明的是如果base和exp是編譯期常量,pow的返回結(jié)果 // 就可以當(dāng)一個編譯期常量使用;如果base和exp中有一個不是編譯期常量,則pow的返回結(jié)果就將在執(zhí)行期計算 constexpr int pow(int base, int exp) noexcept { return (exp == 0 ? 1 : base * pow(base, exp - 1)); } } // namespace int test_constexpr_1() { // constexpr variables constexpr int mf = 20; // 20 is a constant expression constexpr int limit = mf + 1; // mf + 1 is a constant expression constexpr int foo = new_sz(); // foo is a constant expression std::cout << "foo:" << foo << "\n"; // foo:42 // 當(dāng)scale的實參是常量表達式時,它的返回值也是常量表達式;反之則不然 int arr[scale(2)]; // ok int i = 2; //int a2[scale(i)]; // error: scale(i)不是常量表達式 size_t value = scale(i); // ok,constexpr函數(shù)不一定返回常量表達式 std::cout << "value:" << value << "\n"; // value:84 int sz = 1; //constexpr auto array_size = sz; // error, sz的值在編譯期未知 const auto array_size1 = sz; // ok, array_size1是sz的一個const副本 int arr2[product(2, 3)] = { 1, 2, 3, 4, 5, 6 }; std::cout << "arr2[5]:" << arr2[5] << "\n"; // arr2[5]:6 return 0; }
constexpr構(gòu)造函數(shù):盡管構(gòu)造函數(shù)不能是const的,但是字面值常量類的構(gòu)造函數(shù)可以是constexpr函數(shù)。事實上,一個字面值常量類必須至少提供一個constexpr構(gòu)造函數(shù)。
constexpr構(gòu)造函數(shù)可以聲明成=default的形式(或者是刪除函數(shù)的形式=delete)。否則,constexpr構(gòu)造函數(shù)就必須既符合構(gòu)造函數(shù)的要求(意味著不能包含返回語句),又符合constexpr函數(shù)的要求(意味著它能擁有的唯一可執(zhí)行語句就是返回語句)。綜合這兩點可知,constexpr構(gòu)造函數(shù)體一般來說應(yīng)該是空的。我們通過前置關(guān)鍵字constexpr就可以聲明一個constexpr構(gòu)造函數(shù)了。
constexpr構(gòu)造函數(shù)必須初始化所有數(shù)據(jù)成員,初始值或者使用constexpr構(gòu)造函數(shù),或者是一條常量表達式。
constexpr構(gòu)造函數(shù)用于生成constexpr對象以及constexpr函數(shù)的參數(shù)或返回類型。
以下為測試代碼:
namespace { class Debug { public: // constexpr構(gòu)造函數(shù)必須初始化所有數(shù)據(jù)成員 constexpr Debug(bool b = true) noexcept : hw_(b), io_(b), other_(b) {} constexpr Debug(bool h, bool i, bool o) noexcept : hw_(h), io_(i), other_(o) {} constexpr bool any() const noexcept { return hw_ || io_ || other_; } constexpr bool get_hw() const noexcept { return hw_; } constexpr bool get_io() const noexcept { return io_; } constexpr bool get_other() const noexcept { return other_; } void set_hw(bool b) noexcept { hw_ = b; } void set_io(bool b) noexcept { io_ = b; } void set_other(bool b) noexcept { other_ = b; } //constexpr void set_hw(bool b) noexcept { hw_ = b; } // C++14 //constexpr void set_io(bool b) noexcept { io_ = b; } //constexpr void set_other(bool b) noexcept { other_ = b; } private: bool hw_, io_, other_; }; constexpr Debug hw_debug(const Debug& d1, const Debug& d2) noexcept { return d1.get_hw() && d2.get_hw(); // 調(diào)用constexpr成員函數(shù) } } // namespace int test_constexpr_2() { constexpr Debug debug(false, true, false); if (debug.any()) std::cout << "any true" << std::endl; // will output if (debug.get_io()) std::cout << "get_io true" << "\n"; // will output constexpr Debug prod(false); if (prod.any()) std::cout << "any true" << std::endl; // will not output constexpr auto hw = hw_debug(debug, prod); // 使用constexpr函數(shù)的結(jié)果來初始化constexpr對象 std::cout << "hw:" << hw.get_hw() << "\n"; // hw:0 return 0; }
注:以上內(nèi)容主要整理自:《C++ Primer Fifth Edition》、《Effective Modern C++》
C++14中constexpr的使用:
在C++11中,constexpr函數(shù)只能包含一組非常有限的語法,包括但不限于:typedefs、using和一條返回語句。在C++14中,允許的語法集大大擴展,包括最常見的語法,如if語句、多次返回、while或for循環(huán)等。
以下為測試代碼:
namespace { // C++14 constexpr functions may use local variables and loops constexpr int pow2(int base, int exp) noexcept { auto result = 1; for (int i = 0; i < exp; ++i) result *= base; return result; } constexpr unsigned int factorial(unsigned int n) { if (n <= 1) return 1; else return n * factorial(n - 1); } } // namespace int test_constexpr_14_1() { constexpr auto value = pow2(2, 4); std::cout << "pow2 value:" << value << "\n"; // pow2 value:16 constexpr auto value2 = factorial(5); std::cout << "factorial value:" << value2 << "\n"; // factorial value:120 return 0; }
執(zhí)行結(jié)果如下:
GitHub:https://github.com/fengbingchun/Messy_Test
到此這篇關(guān)于C++11/C++14中constexpr的使用的文章就介紹到這了,更多相關(guān)C++ constexpr使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實現(xiàn)十六進制字符串轉(zhuǎn)換成int整形值的示例
今天小編就為大家分享一篇關(guān)于C++實現(xiàn)十六進制字符串轉(zhuǎn)換成int整形值的示例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12c語言實現(xiàn)的貨物管理系統(tǒng)實例代碼(增加刪除 查找貨物信息等功能)
這篇文章主要介紹了c語言實現(xiàn)的貨物管理系統(tǒng),可增加刪除、查找貨物信息、顯示貨物信息、排序貨物銷量等操作,大家參考使用吧2013-11-11