constexpr用于在C++11中申报常量表达式(constexpression),可用于函数返回值、函数参数、数据申报和类结构函数。 
常量表达式指数不会改变,在编译期间得到计算结果,例如: const int i=3; //i是一个常变量
const int j=i+1; //j是一个常变量,i+1是一个常量表达式
int k=23; //k的值可以改变,从而不是一个常变量
const int m=f(); //m不是常变量,m的值只有在运行时才会获取1234复制代码类型:[cpp] 1、constexpr的应用。 1)常量表达函数。 若能在编译过程中确定函数返回值,则可使用constexpr修改函数返回值,使函数成为常量表达式函数。 constexpr int f(){return 1;}1复制代码类型:[cpp] 请注意,constexpr修改函数的返回值需要满足以下条件: (a)函数必须有返回值; (b)函数体只有单一的return语句; (c)return语句中的表达式也必须是常量表达式; 使用前必须对函数进行定义。 2)常量表达式值。 一般而言,如果确定变量为常量表达式,则声明为constexpr类型。 constexpr int i=3; //i是一个常变量constexpr int j=i+1; //i+1是一个常变量constexpr int k=f(); //只有f()是一个constexpr函数时,k才是一个常量表达式123复制代码类型:[cpp] 必须明确的是,在constexpr声明中,如果定义了指针,constexpr只对指针有效,与指针所指的对象无关。 const int *p=nullptr; //p是一个指向整型常量的指针(pointer to const)constexpr int *p1=nullptr; //p1是一个常量指针(const pointer)12复制代码类型:[cpp] 若自定义类型对象为常量表达式,则在定义自定义类型时,需要将constexpr作用于自定义类型的构造函数。 struct MyType {
int i; constexpr MyType(int x):i(x){}
}; constexpr MyType myType(1);12345复制代码类型:[cpp] 作用于自定义类型的constexpr结构函数需要满足以下条件: (a)构造函数体必须为空; (b)初始化列表只能使用常量表达式。 3)其他常量表达式应用。 (a)常量表达式作用于函数模板。 常量表达式可以作用于函数模板,但由于函数模板参数的不确定性,实例化模板函数可能不符合常量表达式的条件。此时,C++11标准自动忽略constexpr。 struct NotConstType {
int i;
NotConstType(int x) :i(x) {}
};
NotConstType myType; //constexpr作用于函数模板
template <typename T> constexpr T ConstExpFunc(T t) { return t;
} int main(){
NotConstType objTmp = ConstExpFunc(myType); //编译通过,ConstExpFunc实例化为普通函数,constexpr被忽略
constexpr NotConstType objTmp1 = ConstExpFunc(myType); //编译**失败**
constexpr int a = ConstExpFunc(1); //编译通过,ConstExpFunc实例化为常量表达式函数
}12345678910111213141516复制代码类型:[cpp] (b)constexpr元编程。 constexpr可以作用于递归函数,实现编译时期的数值计算,即constexpr元编程。根据C++11标准,常量表达式应至少支持512层递归。 constexpr int Fibonacci(int n){ return (n == 1) ? 1 : (n == 2 ? 1 : Fibonacci(n - 1) + Fibonacci(n - 2));
} int main(){ constexpr int fib8 = Fibonacci(8); //编译期常量等于21
}1234567复制代码类型:[cpp] 请注意,constexpr元编程并非C++11标准强制编译器必须实现,编译器可以有选择地实现。换句话说,编译器可能不支持递归常量表达式函数。但也不用太担心,主流C++编译器都是支持的,比如GCC和VC++。 2、constexpr和const的区别。 const可以修改函数参数。函数返回值。函数本身。类const在不同的使用场景中有不同的含义,但在大多数情况下,const描述的是运行时常量性,即数据在运行过程中是不可改变的。 constexpr可以修改函数参数、函数返回值、变量、类结构函数、函数模板等。,这是一种比const更严格的约束。它修改的表达式不仅具有运行时常量,还具有编译时常量,即constexpr修改的表达式值可以在编译过程中知道。我们来看看实际应用的区别: const int getConst(){ return 1; } enum{ e1=getConst(),e2}; //编译出错
//换成constexpr即可在编译期确定函数返回值用于初始化enum常量
constexpr int getConst(){ return 1; } enum{ e1=getConst(),e2}; //编译OK123456复制代码类型:[cpp] 在constexpr出现之前,可以在编译期初始化的const表达式是隐含的常量表达式(implicitconstexpr),直到c++11、constexpr才从const中细分为关键词。 const自1983年C++刚改名以来就存在。面对constexpr,我们应该尽可能合理地使用constexpr来帮助编译器优化代码。
|