美文网首页
处理类型

处理类型

作者: Troll__Zhao | 来源:发表于2016-01-22 13:02 被阅读0次

    随着程序的越来越复杂,程序中用到的类型也越来越复杂,体现在两个方面:

    • 类型名称难于拼写,名字既难记由容易写错,还无法确定其真实目的是什么
    • 有时候根本不知道所需要的类型是什么,我们必须从上下文寻求帮助

    这时候我们主要有三种解决方案:

    1. 类型别名
      类型别名是一个名字,是某种类型的一个同义词。
      传统方法定义别名用的是typedef
    typedef double wages;      //wages是double的同义词
    wages hourly, weekly;       //等同于double hourly, weekly;
    

    C++11标准规定了一种新的办法,即使用别名声明,using:

    using wages = double;    //wages是double的同义词
    wages hourly, weekly;     //等同于double hourly, weekly;
    

    这里需要注意的是,假如某个类型别名指代的是复合类型或者常量,那么把它用到声明语句里就会产生意想不到的后果:

    typedef char *pstring;
    const pstring cstr = 0;    //cstr指向char的常量指针
    const pstring *ps;          //ps是一个指针,它的对象是指向char的常量指针
    

    这里必须要明白,pstring实际上是指向char的指针,所以const pstring就是指向char的常量指针,而非指向常量字符的指针,不能简单的将类型别名替换成他本来的样子

    const char *cstr = 0;     //这是对const pstring cstr的错误理解
    

    2.auto类型说明符
    在我们编程的时候,常常需要把表达式的值赋值给变量,这要求在声明变量的时候知道表达式的类型,然而这一点是很不容易的,所以C++11引入了auto说明符来帮助我们推断表达式所属的类型,由auto的特性我们知道,auto定义的变量必须有初始值。
    这里我们要注意的是,auto可以在同一条语句中声明多个变量,但是一条语句中只能有一个基本数据类型,所以该语句中所有的初始基本数据类型都必须一样

    auto i = 0, *p = &i;        //正确,i是整型,p是整型指针
    auto sz = 0, pi = 3.14   //错误,sz是整型, pi是浮点型
    

    使用auto我们还必须要注意以下几点:

    • 首先,和我们之前所知道的一样,使用引用其实就是使用引用的对象,特别的是,当引用作为初始值的时候,参与初始化的实际上是引用的对象的值。所以,编译器此时以引用对象的类型作为auto的类型:
    int i = 0, &r = i;
    auto a = r;               //a是int型(r是i的别名,而i是int型)
    
    • 其次,auto一般会忽略顶层const,同时底层const会被保留下来:
    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型的指针
    auto e = &ci;                     //e是指向int型常量的指针
    
    • 如果希望推断出来的是一个顶层const,需要明确的指出:
    const auto f = ci;      //ci的推演类型是int,而f是const int
    
    • 还可以将引用的类型设置为auto,此时原来的初始化规则仍然适用:
    auto &g = ci;             //g是一个整型常量引用,绑定到ci
    auto &h = 42;            //错误,非常量引用不可绑定字面值
    const auto &j = 42;   //正确,常量引用绑定字面值
    

    设置一个auto的引用的时候,初始值中的顶层常量属性仍然保留

    • 要在一条语句中定义多个变量,切记,符号&和*只从属于某个声明符,而非基本数据类型的一部分,因此初始值必须是同一种类型:
    auto k = ci, &l = i;         //k是int型, l是int型引用
    auto &m = ci, *p = &ci;  //m是int型常量引用,p是指向int型常量的指针
    auto &n = i, *p2 = &ci    //错误,n是int型引用,而p2必须是指向int型常量的指针,这里确实指向int型的普通指针
    

    3.decltype类型指示符
    有时候会碰到这样的情况,我们想用某个表达式的类型定义某个变量,但是不想用该表达式的值初始化这个变量。C++11给我们提供了decltype说明符,它的作用是返回操作数的数据类型。
    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 &
    decltype(cj) z;                  //错误,z的类型是const int &,必须初始化
    

    下面让我们看一组有趣的情况:

    int i = 42, *p = &i, &r = i;
    decltype(r + 0) b;
    decltype(*p) c
    

    在上述的代码中,decltype(r + 0)返回的类型是int型,这是因为,r作为表达式的一部分,r + 0实际上参与运算的是i + 0,返回的是一个具体的值,而非引用,是int型,但是decltype(r)返回的类型是int &,这点需要明白。

    最后一点需要懂得的是,如果decltype使用的是一个不加括号的变量,那么得到的结果是这个变量的类型,一旦加上括号,得到的是引用类型

    decltype((i)) d;    //错误,d是一个int &,必须初始化
    decltype(i)  e;     //正确,e是一个为初始化的int型变量
    

    相关文章

      网友评论

          本文标题:处理类型

          本文链接:https://www.haomeiwen.com/subject/bctrkttx.html