constexpr 关键字

C++11新标准规定,允许将变量声明为constexpr类型,以便由编译器来验证变量的值是否是一个常量表达式。 constexpr是在编译器判断是否是常量的。

constexpr int mf = 20; //常量
constexpr int limit = mf + 1; //常量
constexpr int sz = size(); //只有size是一个constexpr函数的时候,才是一个正确的语句。

constexpr 与指针混用时, 限定符constexpr仅对指针有效,与指针所指的对象无关。

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

auto 自动变量类型

auto的引入使我们能根据 赋值表达式右边的 表达式来自动推断 左边定义的变量的类型。

auto item = val1 + val2; //item 初始化为val1和val2相加的结果的类型

auto一般会忽略掉顶层 const,而保留 底层const

const int ci = i, &cr = ci;
auto b = ci; //b是int
auto c = cr; //c是int
auto d = &i; //d是 int *
auto e = &ci; //e是 const int *

如果希望推断出的类型是一个顶层const,则需要明确指出

const auto f = ci; // ci的推导类型是int,f则是const int
const auto f = &ci; // &ci的推导类型是const int *, f则是const int const *

还可以将引用的类型设为auto,这时原来的初始化规则仍然适用。

auto &g = ci; //g是int &
auto &h = 42; //错误, h是int &, 而42是字面常量
const auto &j = 42; //正确

记住,在一条语句中定义多个变量,&和*都只从属于某个变量的声明,而不是数据类型的一部分。并且右侧表达式推导出的类型必须是一致的,否则就会有歧义

auto k = ci, &l = i;   //正确 k是int, l是int &
auto &m = ci, *p = &ci; //正确, m是const int &, p是const int *
auto &n = i, *p2 = &ci; //错误, n是int &, p2是 const int *。 这样auto推导产生歧义,所以错误。

decltype 类型指示符

有时候,我们需要用表达式的类型推断出要定义的变量的类型。但是不想用该表达式的值初始化变量,或者该表达式其实在这时候还是不能计算的。为了满足这一要求,C++11引入了decltype关键字。decltype的作用是返回表达式的数据类型。 decltype是在编译期就推断出结果的。

decltype(f()) sum = x;

decltype处理顶层const和引用的方式与auto有些不同。如果decltype使用的表达式是一个变量,则decltype返回该变量的类型,包括顶层const和引用在内。

const int ci = 0, &cj = ci;
decltype(ci) x = 0;  //x是const int
decltype(cj) y = &x; //y是const int &,绑定到x
decltype(cj) z;      //错误,z是const int &,是一个引用,必须被初始化

decltype和引用

  • decltype里面是一个引用时,则结果是一个引用类型
  • decltype里面是一个解引用操作符,则结果也是一个引用
  • decltype里面是双括号,则结果也是引用
int i = 32, *p = &i, &r = i;
decltype(r + 0) b; //正确,b是int
decltype(r) c; //错误, c是int &,必须初始化
decltype(*p) d; //错误, d是int &
decltype((i)) e; //错误,e是int &