c++中,constexpr 让用户显式的声明函数或对象构造函数在编译期会成为常量表达式,这个关键字明确的告诉编译器应该去验证被声明的表达式在编译期就应该是一个常量表达式。
声明为constexpr的变量一定是一个const变量,而且必须用常量表达式初始化:
constexpr int mf = 20; //20是常量表达式 constexpr int limit = mf + 1; // mf + 1是常量表达式 constexpr int sz = size(); //之后当size是一个constexpr函数时才是一条正确的声明语句
需注意constexpr和const在指针上的区别,constexpt只能对指针本身生效,而不针对指针所指向对象
const int*p = nullptr; //p是一个指向整形常量的指针 constexpr int* q = nullptr; //q是一个指向整数的常量指针
更具体的例子如下
#include <iostream> #define LEN 10 int len_foo() { int i = 2; return i; } constexpr int len_foo_constexpr() { return 5; } constexpr int fibonacci(const int n) { return n == 1 || n == 2 ? 1 : fibonacci(n-1)+fibonacci(n-2); } int main() { char arr_1[10]; // 合法 char arr_2[LEN]; // 合法 int len = 10; // char arr_3[len]; // 非法 const int len_2 = len + 1; constexpr int len_2_constexpr = 1 + 2 + 3; // char arr_4[len_2]; // 非法 char arr_4[len_2_constexpr]; // 合法 // char arr_5[len_foo()+5]; // 非法 char arr_6[len_foo_constexpr() + 1]; // 合法 std::cout << fibonacci(10) << std::endl; // 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 std::cout << fibonacci(10) << std::endl; return 0; }
上例中,len_2虽然是const修饰的常数,但是其不能用来初始化一个数组的大小,因为c++标准里数组的长度必须是一个常量表达式,而不是常数,该行为是ub的。
此外constexpr修饰的函数可用递归,c++14后可在constexpr函数内使用局部变量、循环和分支等简单语句。
巧妙的使用constexpr可用减少代码量,见下例
static std::string generate(const Node& node) { return std::visit( //c++17 std::visit(T,val),使用对象class/泛型Lambdas/重载的Lambdas方式访问val [](auto&& arg)->std::string { using T = std::decay_t<decltype(arg)>; //c++14std::decay_t标记c++11std::decay 类型消除,将数据带有的const,&等修饰符关键字去除 if constexpr (std::is_same_v<T, Null>) { return "null"; } else if constexpr (std::is_same_v<T, Bool>) { return arg ? "true" : "false"; } else if constexpr (std::is_same_v<T, Int>) { return std::to_string(arg); } else if constexpr (std::is_same_v<T, Float>) { return std::to_string(arg); } else if constexpr (std::is_same_v<T, String>) { return generate_string(arg); } else if constexpr (std::is_same_v<T, Array>) { return generate_array(arg); } else if constexpr (std::is_same_v<T, Object>) { return generate_object(arg); } }, node.value); }
其中结构体node的成员value是std::variant类型,上例代码使用if constexpr,使得程序在编译器去检测if的合法性,免去了重载多个类型的函数。(二者效果相同)
若此处不采用if constexpr,那么因为编译器无法在运行时确定value的具体类型,该段程序将无法编译成功或运行
参考文章:https://blog.csdn.net/janeqi1987/article/details/103542802
https://changkun.de/modern-cpp/zh-cn/02-usability/
标签:std,return,int,len,constexpr,c++,const From: https://www.cnblogs.com/Explosion556/p/17300950.html