[c++ primer笔记][c++11] auto与decltype

来源:互联网 发布:冒充淘宝客服退款诈骗 编辑:程序博客网 时间:2024/06/05 14:35

文中内容收集整理自《C++ Primer 中文版 (第5版)》,版权归原书所有

1.auto

auto是c++11标准引入的类型说明符, 和原来那些只对应一种特定类型的说明符(如double)不同, auto让编译器通过初始值来推算变量的类型. 因此,auto定义的变量必须有初始值.

使用auto也能在一条语句中声明多个变量, 因为一条声明语句只能有一个基本数据类型,所以该语句中所有变量的初始基本数据类型都必须一样;

   auto i = 0, *p = &i;          // 正确: i是整数, p是整形指针   auto sz = 0, pi = 3.14;       // 错误: sz和pi的类型不一致

复合类型,常量和auto

编译器推断出来的auto类型有时候和初始值的类型并不完全一样, 编译器会适当地改变结果类型使其更符合初始化规则, 下面是它的三个规则:

1.      当引用被用作初始值时, 真正参与初始化的其实是引用对象的值, 此时编译器以引用对象的类型作为auto的类型.

2.      auto一般会忽略顶层const,同时底层const则会保留下来.如果希望推断出的auto类型是一个顶层const, 需要明确指出.

(1)    对常量对象取地址是一种底层const,

(2)    设置一个类型为auto的引用时, 初识值中的顶层常量属性仍然保留.和往常一样, 如果我们给初始值绑定一个引用, 则此时的常量就不是顶层常量了.

上面两点总结起来就是:使用auto类型说明符定义一个指针或者引用时,如果它们所指向的对象具有const属性,则该指针或引用会保留对象的const属性,即与这样的定义语句等价:   const type *p = var ; .

    int i= 0, &r = i;                 const int ci = i, &cr = ci;       auto b = ci;  // b是一个int型变量(ci的顶层const特性被忽略掉了)    auto c = cr;       // c是一个int型变量(cr是ci的别名, ci本身是一个顶层const)    auto d = &i;        // d是一个int型指针(int变量的地址就是指向int类型的指针)    auto e = &ci;       // e是一个指向int型常量的指针(对常量对象取地址是一种底层const)    auto &g = ci;       // g是一个int型常量的引用    auto &h = 42;       // 错误: 不能为一个非常量引用绑定字面值    const auto &j = 42; // 正确: 可以为常量引用绑定字面值

3.      要在一条语句中定义多个变量, 切记, 符号&和*只从属于某个声明符, 而非基本数据类型的一部分, 因此初始值必须是同一种类型.

auto k = ci, &l = i;    // k是int型变量, l是int引用auto &m = ci, *p = &ci; // m是对整型常量的引用, p是指向整型常量的指针auto &n = i, *p2 = &ci; // 错误: i的类型是int而&ci的类型是const int

需要注意的是, 不能简单的认为auto的类型就是初始值的类型, 比如下面的语句

    auto i = 0, *p = &i;     auto p1 = p;    auto *p2 = p1;

如果我们认为auto的类型就是初始值的类型, 那么p2就是一个int**类型的变量, 但p1又是int*类型, 因此按照这种理解第三条语句就是非法的, 因为将int*类型赋值给了int**类型, 实际上这条语句却是合法的, auto在此时被推断为int, p2是一个int*变量.

2.decltype

有时会遇到这种情况: 希望从表达式的类型推断出要定义的变量的类型, 但是不想用该表达式的值初始化变量. 为了满足这一要求, C++11新标准引入了第二种类型说明符decltype, 它的作用是选择并返回操作数的数据类型. 在此过程中, 编译器分析表达式并得到它的类型, 却不实际计算表达式的值, 例如:
decltype(f()) sum = x;    // sum的类型就是函数f的返回类型
编译器并不实际调用函数f, 而是使用当调用发生时f的返回值类型作为sum的类型

1.decltype使用的表达式是一个变量, 则decltype返回该变量的类型(包括顶层const和引用在内)

int i = 42, *p = &i, &r = i;decltype(r + 0) b;  // 正确:加法的结果是int,因此b是一个未初始化的int变量
decltype(*p) c;     // 错误: c是int&, 必须初始化

2. decltype使用的表达式不是一个变量, 则decltype返回表达式结果对应的类型
    (1) 如果表达式是解引用操作, 则decltype将得到引用类型
    (2) decltype使用的是一个不加括号的变量, 则得到的结果是该变量的类型, 如果给变量加上了一层或多层括号, 编译器就会把它当成是一个表达式. 变量是一种可以作为赋值语句左值的特殊表达式, 所以这样的decltype就会得到引用类型.
int i = 42;decltype((i)) d;  // 错误:d是int&, 必须初始化decltype(i) e;    // 正确: e是一个未初始化的int

切记:
decltype((variable))的结果永远是引用, 而decltype(variable)的结果只有当variable本身就是一个引用时才是引用

3. 如果表达式的求职结果是左值, decltype作用域该表达式(不是变量)得到一个引用类型

3. auto,decltype与数组

1. 定义数据组时必须制定数组的类型, 不允许使用auto关键字由初始值的列表推断类型;
2. 在一些情况下数组的操作实际上是指针的操作, 因此, 当使用数据作为一个auto变量的初始值时, 推断得到的类型是指针而非数组;
    但, 使用decltype关键字时, 会获得一个数组类型.



原创粉丝点击