详解字面值、常量表达式和constexpr变量和字面值类型

一张包含多个文件列表的图片
常量相关概念辨析

字面值常量

指的是像42这样的值,直观上很容易理解。

每个字面值常量都对应一种数据类型,其形式和值决定了其数据类型,包括:

整型和浮点型字面值、字符和字符串字面值、布尔字面值和指针字面值:

bool test = false;
// nullptr是指针字面值

常量表达式

指在编译过程中其值不会改变且能够得到计算结果的表达式。

显然,字面值属于常量表达式,使用常量表达式初始化的const对象也属于常量表达式。

对象是否是常量表达式由其数据类型和初始值共同决定。例如:

const int max_files = 20;  // 常量表达式
const int limit = max_files + 1; // limit是常量表达式
int staff_size = 27; // staff_size不是常量表达式
const int sz = get_size(); // sz不是常量表达式,因为在编译期间不能得到sz的值,只有在运行时才能得到

constexpr变量

在C++语言中,有几种情况需要使用常量表达式。

尽管我们可以定义一个const变量并将其初始值设为我们认为的某个常量表达式,但在复杂的系统中,很难(几乎不可能)确定初始值是否为常量表达式。因此,在实际使用中,尽管我们意图将一个const变量的初始值设为常量表达式,但在实际运行中,我们发现这并非总是成立。在这种情况下,对象的定义和使用是截然不同的。

C++11规定,允许将变量声明为constexpr类型,以便编译器验证变量的值是否为常量表达式。

声明为constexpr的变量一定是常量,且必须用常量表达式初始化。

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

字面值类型

常量表达式的值需要在编译时计算,因此对声明constexpr时使用的类型必须有所限制。这些类型统称为字面值类型(literal type)。

算术类型、引用和指针都是字面值类型。

constexpr int a = 0; // 算术类型int是字面值类型

某些类也属于字面值类型,这些类被称为字面值常量类。例如,假设Debug是一个字面值常量类,则:

constexpr Debug debug(args); // 生成一个constexpr对象-debug

发表评论

0 评论