C++ 中 auto 与 decltype 的用法与区别

最近在恶补 C++ 知识的时候,学习到了一些 C++11 标准的新特性,利用这些新特性,我们能够更快地提高编程效率,从而实现我们的目标,在此特意记下学习过程中所学习到的一些东西,方便日后的回顾和复习。

auto 关键字

在我们日常编程的时候,我们常常需要把表达式的值赋给变量,需要在声明变量的时候,我们必须清楚的知道变量是属于什么类型的。然而往往有些时候,我们做到这一点并非易事。为了解决这个问题, C++11 新标准就引入了 auto 类型说明符,通过使用 auto 关键字,我们就能让编译器替我们去分析表达式所属的类型,和原来那些只对应某种特定的类型说明符(例如 int )不同, auto 能让编译器通过初始值来进行类型推演,从而获得定义变量的类型,这样一来,我们就可以大大地降低我们在编程中出现变量类型错误的概率了。

需要注意的一点??:auto 定义的变量必须有初始值。

举个例子:

#include <iostream>
#include <typeinfo>
using namespace std;

int main(int argc, const char *argv[])
{
  auto value1 = 1;
  auto value2 = 2.33;
  auto value3 = 'a';
  std::cout << "value1 的类型是 " << typeid(value1).name() << std::endl;
  std::cout << "value2 的类型是 " << typeid(value2).name() << std::endl;
  std::cout << "value3 的类型是 " << typeid(value3).name() << std::endl;
  return 0;
}

运行结果如下:

value1 的类型是 i
value2 的类型是 d
value3 的类型是 c

注: typeid() 操作符可以输出变量的类型,其库函数在 头文件中,如上面??这个例子所示。

编译器推断出来的 auto 类型有时候会跟初始值的类型并不完全一样,编译器会适当的改变结果类型,使得其更符合初始化规则。例如我们平常用的浮点数类型 float 和 double ,编译器似乎会优先选择 double 类型。

但 auto 需要注意的一点就是,使用 auto 能在一个语句中声明多个变量,但是一个语句在声明多个变量的时候,只能有一个基本数据类型,所以该语句中所有变量的初始基本数据类型都必须是一样的。在这里一定要区别数据类型和类型修饰符!!

例如:

我们在上面代码中增加 value4 和 value5:

auto value4 = "QAQ", value5 = &value1;

我们可以看到,在编译时出现了报错,原因是因为 value4 推断出的类型是字符串型,而 value5 推断出来的类型是指针类型,一条语句在声明多个变量的时候,只能有一个基本数据类型,所以会有如下的错误出现。

decltype 关键字

而 decltype 类型说明符也是 C++11 的标准,它是用于从表达式的类型推断出要定义的变量的类型。

因为在有些时候,我们会遇到如下这种情况:

我们希望从表达式中推断出要定义变量的类型,但却不想用表达式的值去初始化变量,或者当函数的返回值类型为某表达式的值的类型,这个时候, auto 显得就很无力了,所以 C++11 又引入了第二种类型说明符 decltype 。它的作用是选择并返回操作数的数据类型。在此过程中,编译器只是分析表达式或函数的返回值的类型并得到它的类型,却不进行实际的计算表达式的值。

举个例子:

#include <iostream>
#include <typeinfo>
using namespace std;

std::string func(){
  return "Hello World!";
}

int main(int argc, const char *argv[])
{
  decltype(func()) a;
  int i;
  decltype(i) b;
  std::cout << "a 的类型是 " << typeid(a).name() << std::endl;
  std::cout << "b 的类型是 " << typeid(b).name() << std::endl;
  return 0;
}

输出结果如下:

a 的类型是 NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
b 的类型是 i

注:decltype()括号中的表达式并不去执行,而 decltype((variable)) 的结果永远是引用,而 decltype((variable)) 只有当 variable 本身是一个引用是才是引用。

auto 关键字和 decltype 关键字的区别

对于 decltype 所用的表达式来说,如果变量名加上一对括号,则得到的类型与不加上括号的时候可能不同。

如果 decltype 使用的是一个不加括号的变量,那么得到的结果就是这个变量的类型。但是如果给这个变量加上一个或多层括号,那么编译器会把这个变量当作一个表达式看待,变量是一个可以作为左值的特殊表达式,所以这样的decltype就会返回引用类型。

如:

int i;
decltype(i) // int类型
decltype((i)) // int& 类型

在这里我们不探讨太多的一些具体的细节,只介绍一些常用的一些用法和注意事项,想了解更多的话参考 C++ Primer Plus 。

原文地址:https://www.cnblogs.com/ECJTUACM-873284962/p/10747751.html

时间: 2024-11-06 07:10:39

C++ 中 auto 与 decltype 的用法与区别的相关文章

【Java学习笔记之二十九】Java中的&quot;equals&quot;和&quot;==&quot;的用法及区别

Java中的"equals"和"=="的用法及区别 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str2 = new String("hello"); 3 System.out.println(str1==str2); 4 System.out.println(str1.equals(str2)); 为什么第4行和第5行的输出结果不一

auto和decltype的用法总结

一, auto 1, auto的作用 一般来说, 在把一个表达式或者函数的返回值赋给一个对象的时候, 我们必须要知道这个表达式的返回类型, 但是有的时候我们很难或者无法知道这个表达式或者函数的返回类型. 这个时候, 我们就可以使用auto关键字来让编译器帮助我们分析表达式或者函数所属的类型. 比如: auto item = val1 + val2; auto red = LayerColor::create(Color4B(255, 100, 100, 255), 200, 100); 如果va

php中get_cfg_var()和ini_get()的用法及区别

php里get_cfg_var()和ini_get()都是取得配置值的函数,当你需要获取php.ini里的某个选项的配置值时,这两个函数都都可以使用,得到的结果是一样的. 不过,get_cfg_var()和ini_get()也有一些区别,这便是本文要谈的内容. 在说这两个函数区别之前,我们先来了解一下它们的含义及用法. 有关ini_get()的用法,前面有一篇<php用ini_get获取php.ini里变量值的方法>,这里不再累赘. 下面主要说说get_cfg_var()函数. get_cfg

php中session_unset与session_destroy的用法与区别,做退出的执行顺序

区别: session_unset()释放当前在内存中已经创建的所有$_SESSION变量,但不删除session文件以及不释放对应的session id session_destroy()删除当前用户对应的session文件以及释放session id,内存中的$_SESSION变量内容依然保留 因此,释放用户的session所有资源,需要顺序执行如下代码: <?php$_SESSION['user'] = 'user1′;session_unset();session_destroy();?

jQuery中delegate与on的用法与区别

在jQuery1.7中 .delegate()已被.on()取代.对于早期版本,它仍然使用事件委托的最有效手段. 在事件绑定和委派,delegate()和on在一般情况下,这两种方法是等效的. .delegate() 指定的元素(属于被选元素的子元素)添加一个或多个事件处理程序,并规定当这些事件发生时运行的函数. // jQuery 1.4.3+ $( elements ).delegate( selector, events, data, handler ); // jQuery 1.7+ $

Vue中Computed和Watch的用法及区别

一. 计算属性(computed) 1.计算属性是为了模板中的表达式简洁,易维护,符合用于简单运算的设计初衷. 例如: <p id="app"> {{ myname.substring(0,1).toUpperCase() + myname.substring(1) }} </p> 运算过于复杂,冗长,且不好维护,因此我们对于复杂的运算应该 使用计算属性的方式去书写. 因此可改写为: <body> <div id="app"

matlab 中randn randi rand 的用法以及区别

1,rand 生成均匀分布的伪随机数.分布在(0~1)之间 主要语法:rand(m,n)生成m行n列的均匀分布的伪随机数                      rand(m,n,'double')生成指定精度的均匀分布的伪随机数,参数还可以 是'single'                     rand(RandStream,m,n)利用指定的RandStream(我理解为随机种子)生成伪 随机数 2,randn 生成标准正态分布的伪随机数(均值为0,方差为1)     主要语法:和上

python中yield与return的用法与区别

生成器:函数内带有yield关键字,那么,这个函数执行的结果就是生成器. 生成器,本质就是迭代器. return与,yield 1,return只能返回一次函数就彻底结束了.而yield能返回多次值. 2,yield把函数变成生成器---迭代器--->把iter,next方法给到函数了.为我们自己定义迭代器,提供了方便. 3,yield能保存函数在暂停,和继续下一次云形时的状态. 原文地址:https://www.cnblogs.com/catherine007/p/8309474.html

css中auto的用法

—什么是auto? +auto是自适应的意思,auto是很多尺寸值的默认值,也就是由浏览器自动计算. +块级元素中margin.border.padding以及content宽度之和构成父元素width. 使用auto属性后,父元素宽度发生变化,该元素的宽度也会随之变化. 下图中   auto 的值就是margin.border.padding以及content宽度之和 +但是当该元素被设为浮动时,该元素的width就变成了内容的宽度了,由内容撑开,也就是所谓的有了包裹性.       over