使用constexpr
以让编译器来检查该值是否是常量表达式,降低程序员负担。
const
与
constexpr
constexpr
修饰的表达式,需要在编译时就确定其值,且该值以后不可被改变。而const
修饰的表达式,是在运行时才能够确定其值:
所有的constexpr
都是const
的,但所有的const
都不一定是constexpr
的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include <vector> #include <iostream> #include <array>
int main(void) {
int sz; constexpr auto array_size = sz; std::array<int, sz> array1;
constexpr int sz2 = 20; std::array<int, sz2> array2;
return 0; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include <vector> #include <iostream> #include <array>
int main(void){
int sz; const auto array_size = sz; std::array<int, array_size> array1;
return 0; }
|
constexpr
函数
constexpr
函数具有的特性:
- 当传入该函数的实参是
constexpr
时,该函数的结果就是可以在编译期确定的。
- 如果传入的实参不是
constexpr
的,该函数就是普通的在运行时确定的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include <vector> #include <iostream> #include <array>
constexpr int pow(int base, int exp) noexcept { return (exp == 0 ? 1 : base * pow(base, exp - 1));
}
int main(void) {
constexpr int exp = 5; std::array<int, pow(3, exp)>();
int exp2 = 10; std::cout << "Result " << pow(2, exp2) << "\n";
return 0; }
|
constexpr
类
如下的类:
1 2 3 4 5 6 7 8 9 10 11 12
| class Point { public: constexpr Point(double xVal = 0, double yVal = 0) noexcept : x(xVal), y(yVal) {} constexpr double xValue() const noexcept { return x; } constexpr double yValue() const noexcept { return y; } void setX(double newX) noexcept { x = newX; } void setY(double newY) noexcept { y = newY; } private: double x, y; };
|
当构造函数被传入的实参是constexpr
的是,这个类所实例化的对象也是constexpr
的,进而该类就可以被constexpr
函数所调用:
1 2 3 4 5 6 7 8 9 10 11 12
| constexpr Point midpoint(const Point& p1, const Point& p2) noexcept { return { (p1.xValue() + p2.xValue()) / 2, (p1.yValue() + p2.yValue()) / 2 }; } constexpr Point p1(9.4, 27.7); constexpr Point p2(28.8, 5.3);
constexpr auto mid = midpoint(p1, p2);
|
最终以上对象的创建都是在编译期就完成了,虽然编译的时间会加长,但是代码的运行效率确更高。