【C++】constexpr和常量表达式

  常量表达式(const expression)是指值不会改变并且在编译过程就能得到计算结果的表达式。显然,字面值属于常量表达式,用常量表达式初始化的const对象也是常量表达式。后面将提到,C++语言有几种情况下是要用到常量表达式的。

  一个对象(或者表达式)是不是常量表达式由它的数据类型和初始值共同决定,例如:

    const int max_files = 20;           //max_files是常量表达式
    const int limit = max_files + 1;    //limit是常量表达式
    int staff_size = 27;                //staff_size不是常量表达式
    const int sz = get_size();          //sz不是常量表达式

尽管staff_size的初始值是字面值常量,但由于它的数据类型只是一个int而非const int,所以它不属于常量表达式。另一方面,尽管sz本身是一个常量,但它的具体值直到运行时才能获取到,所以也不是常量表达式。

constexpr变量

  在一个复杂的系统中,很难(几乎肯定不能)分辨一个初始值到底是不是常量表达式。当然可以定义一个const变量并把它的初始值设为我们认为的某个常量表达式,但在实际使用时,尽管要求如此却常常发现初始值并非常量表达式的情况。可以这么说,此种情况下,对象的定义和使用是两回事儿。

  C++新标准规定,允许将变量声明为constexpr类型以便由编译器来验证变量是否是一个常量表达式。声明为constexpr的变量一定是一个常量,而且必须由常量表达式初始化:

    constexpr int mf = 20;          //20是常量表达式
    constexpr int limit = mf + 1;   //mf + 1是常量表达式
    constexpr int sz = size();      //只有当size是一个constexpr函数时才是一条正确的声明语句

字面值类型

  常量表达式的值需要在编译时就能得到计算,因此对声明constexpr时用到的类型必须有所限制。因为这些类型一般比较简单,值也显而易见,就把它们称为“字面值类型”(literal type)。

  到目前为止接触过的数据类型中,算术类型、引用和指针都属于字面值类型。自定义类Sales_item、IO库、string类型则不能被定义为constexpr。

  尽管指针和引用都能定义成constexpr,但它们的初始值却受到严格的限制。一个constexpr指针的初始值必须是nullptr或者0,或者是存储于某个固定地址中的对象。

  函数体内定义个变量一般来说并非存放在固定地址中,因此constexpr指针不能指向这样的变量。相反的,定义在所有函数体之外的对象其地址固定不变,能用来初始化constexpr指针。允许函数定义一类有效范围超过函数本身的变量,这类变量和定义在函数体之外的变量一样也有固定地址。因此,constexpr引用能绑定到这样的变量上,constexpr指针也能指向这样的变量。

指针和constexpr

  必须明确一点,在constexpr中如果定义了一个指针限定符constexpr仅对指针有效,与指针所指的对象无关:

    const int *p = nullptr;         //p是一个指向整形常量的指针
    constexpr int *q = nullptr;     //q是一个指向整数的常量指针

p和q的类型相差甚远,p是一个指向常量的指针,而q是一个常量指针,其中的关键在于constexpr把它所定义的对象置为了顶层const。

  与其它常量指针类似,constexpr指针既可以指向常量也可以指向非常量:

    constexpr int *np = nullptr;    //np是一个指向整数的常量指针,其值为空
    int j = 0;
    constexpr int i = 42;           //i的类型是整型常量,i和j都必须定义在函数体之外
    constexpr const int *p = &i;    //p是常量指针,指向整形常量i
    constexpr int *p1 = &j;         //p1是常量指针,指向整数j

原文地址:https://www.cnblogs.com/bootblack/p/11551316.html

时间: 2024-10-10 20:16:32

【C++】constexpr和常量表达式的相关文章

constexpr与常量表达式(c++11标准)

常量表达式(const expression):是指值不会改变并且在编译过程中就得到计算结果的表达式.(运行中得到结果的不能成为常量表达式). const int i=3;    //是一个常量表达式 const int j=i+1; //是一个常量表达式 int k=23;        //k的值可以改变,从而不是一个常量表达式 const int m=f(); //不是常量表达式,m的值只有在运行时才会获取. constexpr变量: C++11允许声明constexpr类型来由编译器检验

c++ 11学习笔记-- 常量表达式(constexpr)

最新在弄android ndk相关的,惊奇的发现最新的ndk10的版本已经gcc4.9了,我印象中,gcc4.8就支持C++0x11,14的支持,gcc再次走到了llvm的前面,LLVM最新的版本3.4.2应该只支持c++ 11,如果是同样的c++代码我一直认为llvm的效率会明显强过gcc. 废话不多说,让我们开始学习c++ 11吧,说实话我之前一直都很抗拒c++新的语法,感觉太难接受了,现在看来不熟悉也不行了. 常量表达式(constexpr) 常量表达式机制是为了: 提供了更多的通用的值不

c++11 常量表达式

c++11 常量表达式 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #include <vector> #include <map> /** * 常量表达式主要是允许一些计算发生在编译时,即发生在代码编译而不是运行的时候. * 这是很大的优化:假如有些事情可以在编译时做,它将只做一次,而不是每次程序运行时都计算. */ /* constexpr函数的限制: 函数中

常量表达式

常量表达式 Item 1:如果函数必须在编译期进行求值,就将其声明为constexpr 理由 需要用constexpr来告诉编译器允许对其进行编译期求值. 示例 阶乘的例子: constexpr int fac(int n) //constexpr函数 { return (n>1) ? n*fac(n-1) : 1; } void f(int n) { int f5 = fac(5); //在编译期间可能进行了求值 int fn = fac(n); //在运行期间进行了求值(因为实参n是变量)

Android studio常量表达式的错误

今天在AS上集成Zxing的库,出现了如下的错误: 常量表达式的错误 这个错误是switch case的问题,提示换成if else 在AS中我们使用Alt+Enter(opt+Enter for Mac)快捷键直接将switch转换为if else,如下图所示: 在Tools Android的网站上有详细的说明,主要是避免多个库之间出现资源冲突 Non-constant Fields in Case Labels In a regular Android project, constants

java 常量表达式

原文地址:http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28 这是我翻译的,以备不时之用. 常量表达式是一个代表基本数据类型或者String数据类型的表达式,是在编译期间能计算出来的值.由以下几点组成: 基本数据类型或者String数据类型的字面值 转换成基本数据类型或者String(这点不是很理解) 一元操作符:+,-,~,and,!(但不包括++or--) 乘法操作符: *,/ 移位运算符: <<,&

外部变量初始化与常量表达式

代码: #include <stdio.h> #include <stdlib.h> // 外部存储类(external storage class):具备文件作用域.外部链接和静态存储时期的类型 // 外部变量(external variable):具备外部存储类的变量 int a; // 外部变量如果不进行显式初始化,会被自动赋初值0 int b; int ages[10]; // 文件作用域变量只可用常量表达式初始化 // 只要不是变长数组,sizeof表达式就被认为是常量表

java编译器对string常量表达式的处理和优化

首先把问题摆出来,先看这个代码 String a = "ab";  String b = "a" + "b";  System.out.println((a == b)); 打印结果会是什么?类似这样的问题,有人考过我,我也拿来考过别人(蛮好玩的,大家也可以拿来问人玩),一般答案会是以下几种: 1.true     "a" + "b" 的结果就是"ab",这样a,b都是"ab&

错误提示:在此上下文中不允许使用名称 &quot;***&quot;。有效表达式包括常量、 常量表达式和变量(在某些上下文中),不允许使用列名。

出现这种情况的原因,是因为在SQL语句的编写格式不正确. 事例展示: 错误: 1 string sql = "insert into person ([name], sex, salary) values ('text_name ', 'text_sex ', text_salary )"; 正确: 1 string sql = "insert into person ([name], sex, salary) values ('" + text_name + &q