• auto和decltype


    auto:

    auto能让编译器通过初始值来推算变量的类型。显然auto定义的变量必须有初始值:

    1 int val1 =1;
    2 
    3 int val2 = 2;
    4 
    5 auto cnt = val1 + val2;//val1+val2的结果是int类型,因此cnt也是int类型

    使用auto也能在一条语句中声明多个变量。因为一条语句只能有一个基本类型,所以该语句中所有变量的初始值的变量类型必须一致:

    1 auto cnt1 = 1, cnt2 = 1;//正确
    2 
    3 auto x1 = 0, x2 = 3.14;//错误

    复合类型,常量和auto:

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

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

    int cnt = 1, &x = cnt;

    auto y = x;//y是int类型,和x的引用对象cnt一致

    auto一般会忽略掉顶层const,保留底层const,比如初始值是一个指向常量的指针时:

     1 int cc = 0;
     2 
     3 const int cnt = cc, &x = cnt;
     4 
     5 auto a = cnt;//a是一个int类型(cnt的顶层const被忽略掉了)
     6 
     7 auto b = x;//b是一个int类型,x是cnt的别名,而x是一个顶层const
     8 
     9 auto c = &cc;//c是一个指向int变量的指针(int变量的地址就是指向int类型的指针)
    10 
    11 auto d = &cnt;//d是一个指向int常量的指针(对常量对象取地址是一种底层const)
    12 
    13 //如果希望推断出的auto类型是一个顶层const,需要明确指出
    14 
    15 const auto e = cnt;//cnt推演类型是int,e的类型是const int
     1 int cnt = 2;
     2 
     3 int cc = 1;
     4 
     5 const int *x = &cnt;
     6 
     7 auto y = x;
     8 
     9 // *y += 1;//底层const保留了,所以y和x一样是一个指向常量cnt的指针,不能通过改变y来修改cnt的值
    10 
    11 cout << x << " " << y << endl;//x和y的值相同,都是存储的cnt的地址
    12 
    13 int *const p = &cnt;
    14 
    15 auto gg = p;//顶层const被忽略了,即gg是一个指向int的指针
    16 
    17 gg = &cc;//所以gg的值可以修改,即gg可以指向其他对象

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

    1  const int cnt = 1;
    2 
    3 auto &a = cnt;//a是一个int常量引用,绑定到cnt
    4 
    5 //auto &b = 1024;//错误,不能非常量引用绑定字面值
    6 
    7 const auto &b = 1024;//可以为常量引用绑定字面值

    通过上面第二条语句还可以发现设置一个类型为auto的引用时,初始值中的顶层const仍然保留。但是给初始值绑定一个常量引用则此时顶层常量会被忽略。

    decltype:

    有时会遇到这种情况:希望从表达式的类型推断出要定义的变量的类型,但是不想用该变量的表达式初始化变量。为了满足这一要求,c++11标准引入了类型说明符decltype,它的作用时选择并返回操作数的数据类型。在此过程中,编译器会分析表达式并得到它的类型,却不实际计算表达式的值:

    decltype(f()) sum = x;//sum的类型就是函数 f 的返回类型

    编译器并不实际调用函数 f,而是使用当调用发生时 f 的返回值类型作为 sum 的类型。

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

    1 const int x = 0, &cnt = x;
    2 
    3 decltype(x) a = 0;//a的类型是const int
    4 
    5 decltype(cnt) b = a;//b的类型是const int&, 绑定的对象是a
    6 
    7 // decltype(cnt) c;//c是一个引用,必须初始化

    值得注意的是引用从来都是作为其所绑定对象的同义词出现,只有在 decltype 处是一个例外。

    如果 decltype 使用的表达式不是一个变量,则 decltype 返回表达式结果对应的类型:

    1 int cnt = 1024, *p = &cnt, &r = cnt;
    2 
    3 decltype(r + 0) b;//r + 0的结果是一个int类型,因此b是一个为初始化的int变量
    4 
    5 decltype(*p) c;//错误,c是int&类型,必须初始化

    通过第三条语句可以发现,如果表达式的内容是解引用操作,则 decltype 将得到引用类型。正如我们所熟悉的那样,解引用指针可以得到指针所指的对象,而且还能给这个对象赋值。因此 decltype(*p) 的结果类型是 int&,而非 int。

    还需要特别当心的是,decltype 的结果类型与表达式形式密切相关。对于 decltype 所用的表达式来说,如果变量名加上了一对括号,则得到的类型与不加是有区别的。后者得到的结果就是表达式结果的类型,而前者得到的类型一定是引用类型。因为如果给变量加上了一层或多层括号,编译器就会把它当成是一个表达式。变量是一种可以作为赋值语句左值的特殊表达式,所以这样的 decltype 就会得到引用类型:

    1 int cnt = 0, x = 1024;
    2 
    3 decltype(cnt) a;//a是一个int类型变量
    4 
    5 decltype((cnt)) b = x;//b是一个int&类型
    6 
    7 decltype(((cnt))) c = x;//c是一个int&类型
  • 相关阅读:
    Oracle列转行函数Listagg以及pivot查询示例
    Java执行操作系统命令
    JUnit学习之hamcrest、testSuite介绍及测试原则
    JUnit学习之JUnit的基本介绍
    Oracle笔记-Multitable INSERT 的用法
    Oracle 11g 新特性 --SQL Plan Management 说明
    Java习惯用法总结
    将Eclipse的Java Project转换为Dynamic Web Project
    在Eclipse中调试web项目
    在Eclipse中添加Servlet-api.jar的方法
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/7898334.html
Copyright © 2020-2023  润新知