分享

C++定义类的关键字——constexpr

 码农9527 2021-12-14

  constexpr用于在C++11中申报常量表达式(constexpression),可用于函数返回值、函数参数、数据申报和类结构函数。

C++定义类的关键字——constexpr

  常量表达式指数不会改变,在编译期间得到计算结果,例如:

  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来帮助编译器优化代码。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多