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

简介: 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


5cbc8635b15c0.png


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

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

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

例如:

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

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

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


5cbc866ab843c.png

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
C++ 复制 全屏


5cbc869507b7f.png

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

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

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

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

如:

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

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

目录
相关文章
|
30天前
|
存储 算法 编译器
【C++ TypeName用法 】掌握C++中的TypeName:模板编程的瑞士军刀
【C++ TypeName用法 】掌握C++中的TypeName:模板编程的瑞士军刀
237 0
|
1月前
|
存储 算法 C++
【C/C++ Vector容量调整】理解C++ Vector:Reserve与Resize的区别与应用
【C/C++ Vector容量调整】理解C++ Vector:Reserve与Resize的区别与应用
50 1
|
1月前
|
编译器 C++ Python
【C/C++ 泡沫精选面试题02】深拷贝和浅拷贝之间的区别?
【C/C++ 泡沫精选面试题02】深拷贝和浅拷贝之间的区别?
32 1
|
1月前
|
存储 JSON 算法
C++ JSON库 nlohmann::basic_json::boolean_t 的用法
C++ JSON库 nlohmann::basic_json::boolean_t 的用法
35 0
|
22天前
|
人工智能 安全 机器人
【C++】const_cast基本用法(详细讲解)
【C++】const_cast基本用法(详细讲解)
|
22天前
|
人工智能 机器人 中间件
【C++】C++回调函数基本用法(详细讲解)
【C++】C++回调函数基本用法(详细讲解)
|
29天前
|
算法 安全 编译器
【C++ 17 新特性 折叠表达式 fold expressions】理解学习 C++ 17 折叠表达式 的用法
【C++ 17 新特性 折叠表达式 fold expressions】理解学习 C++ 17 折叠表达式 的用法
23 1
|
29天前
|
算法 编译器 程序员
深入理解C++编译模式:了解Debug和Release的区别
深入理解C++编译模式:了解Debug和Release的区别
62 2
|
1月前
|
算法 安全 Unix
【C++ 20 信号量 】C++ 线程同步新特性 C++ 20 std::counting_semaphore 信号量的用法 控制对共享资源的并发访问
【C++ 20 信号量 】C++ 线程同步新特性 C++ 20 std::counting_semaphore 信号量的用法 控制对共享资源的并发访问
30 0
|
1月前
|
算法 编译器 C++
【C++ 关键字的混合使用 】C++深度探索:auto、static、constexpr的交互影响与应用
【C++ 关键字的混合使用 】C++深度探索:auto、static、constexpr的交互影响与应用
31 0

热门文章

最新文章