C++11:自动类型推导 auto 和 decltype(下)

前面两篇文章分别介绍了 auto 和 decltype,今天聊聊它们两者之间的区别。

语法格式的区别

auto varname = value; // auto的语法格式
decltype(exp) varname [= value]; // decltype的语法格式

其中,varname 表示变量名,value 表示赋给变量的值,exp 表示一个表达式,方括号[]表示可选。

auto 要求变量必须初始化,也就是在定义变量的同时必须给它赋值;而 decltype 不要求,初始化与否都不影响变量的类型。

这很容易理解,因为 auto 根据变量初始值来推导出变量类型,如果不初始化,变量的类型也就无法推导。

推导规则不同

autodecltype 都会自动推导出变量 varname 的类型:

  • auto 根据 = 右边的初始值 value 推导出变量的类型;
  • decltype 根据 exp 表达式推导出变量的类型,跟 = 右边的 value 没有关系。

auto 将变量的类型和初始值绑定在一起,而 decltype 将变量的类型和初始值分开;虽然 auto 的书写更加简洁,但 decltype 的使用更加灵活。

应用场景不同

auto 通常用于变量声明时,简化类型定义,特别是当类型名较长或复杂时。

decltype 常用于需要精确类型匹配的场景,如模板元编程、泛型编程中,以及定义依赖于表达式类型的变量。

对 cv 限定符的处理

cv 限定符constvolatile 关键字的统称:

  • const 关键字表示数据是只读的,也就是不能被修改;
  • volatile 表示数据是可变的、易变的,目的是不让 CPU 将数据缓存到寄存器,而是从原始的内存中读取。

在推导变量类型时,auto 和 decltype 对 cv 限制符 的处理是不一样的。decltype 会保留 cv 限定符,而 auto 有可能会去掉 cv 限定符。

以下是 auto 关键字对 cv 限定符的推导规则:

  • 如果表达式的类型不是指针或者引用,auto 会把 cv 限定符直接抛弃,推导成 non-const 或者 non-volatile 类型。
  • 如果表达式的类型是指针或者引用,auto 将保留 cv 限定符。

下面的例子演示了对 const 限定符的推导:

int main() {// 非指针非引用类型const int n1 = 0;auto n2 = 10; // n2 是 intn2 = 99;decltype(n1) n3 = 20; // n3 是 const intn3 = 5;  // 错误// 指针类型const int *p1 = &n1;auto p2 = p1; // p2 是 const int **p2 = 66;  // 错误decltype(p1) p3 = p1; // p3 是 const int **p3 = 19;  // 错误
}

编译结果:

编译错误

在 C++ 中无法将一个变量的完整类型输出,我们通过对变量赋值来判断它是否被 const 修饰;如果被 const 修饰那么赋值失败,如果不被 const 修饰,那么赋值成功。虽然这种方案不太直观,但也是能达到目的的。

n2 赋值成功,说明不带 const,也就是 const 被 auto 抛弃了,这验证了 auto 的第一条推导规则。p2 赋值失败,说明是带 const 的,也就是 const 没有被 auto 抛弃,这验证了 auto 的第二条推导规则。

n3 和 p3 都赋值失败,说明 decltype 不会去掉表达式的 const 属性。

对引用的处理

当表达式的类型为引用时:

  • decltype 会保留引用类型;
  • auto 会抛弃引用类型,直接推导出它的原始类型。

请看下面的例子:

#include <iostream>int main() {int n = 15;int &r1 = n;//auto推导auto r2 = r1;r2 = 20;std::cout << n << ", " << r1 << ", " << r2 << std::endl;//decltype推导decltype(r1) r3 = n;r3 = 115;std::cout << n << ", " << r1 << ", " << r3 << std::endl;return 0;
}

输出

15, 15, 20
115, 115, 115

从运行结果可以看出,给 r2 赋值并没有改变 n 的值,这说明 r2 没有指向 n,单独拥有了一块内存,这就证明 r2 不再是引用类型,它的引用类型被 auto 抛弃了。

给 r3 赋值,n 的值也跟着改变,说明 r3 仍然指向 n,它的引用类型被 decltype 保留了。

总结

auto 书写格式比 decltype 简单,但它的推导规则复杂,有时候会改变表达式的原始类型;而 decltype 比较纯粹,一般会坚持保留原始表达式的任何类型。

从代码的健壮性考虑,推荐使用 decltype,但是 decltype 有时显得比较麻烦,尤其是当表达式比较复杂时,例如:

std::vector<int> nums;
decltype(nums.begin()) it = nums.begin();

而如果使用 auto 就会简单很多:

std::vector<int> nums;
auto it = nums.begin();

在实际开发中,如果明确知道使用的变量类型,那么使用 auto,减少代码量,增加可读性,其他场景使用 decltype

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/544312.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mybatis源码阅读系列(二)

前言 上一篇文章mybatis源码阅读系列&#xff08;一&#xff09;介绍了mybatis和原生jdbc的区别&#xff0c;并通过代码展示了两者的运行过程和结果&#xff0c;下面让我们继续详细了解下mybatis的执行过程&#xff1b; package com.wyl.mybatis.service;import com.wyl.mybat…

Linux中 vim 编辑器的使用

文章目录 前言一、vim编辑器模式二、简单的插入、保存和退出三、 命令模式下常用命令即其作用1. 命令模式 思维导图 前言 首先&#xff0c;了解一下 什么是vim 编辑器&#xff1f;在不同的系统中&#xff0c;文本的管理也会不同&#xff1b;windos系统就不多说了&#xff0c…

【运维】StarRocks数据迁移到新集群(针对于集群互通、不互通的情况)

文章目录 一. 迁移整体思路1. 对于新旧集群互通的情况2. 对于新旧集群不互通的情况 二、迁移过程&#xff08;两个集群互通的情况&#xff09;1. 备份过程1.1. 通过mysqlclient与starrocks进行关联1.2. 创建仓库与minio建立联系1.3. 备份数据到minio 2. 迁移过程2.1. 通过mysql…

Web核心,HTTP,tomcat,Servlet

1&#xff0c;JavaWeb技术栈 B/S架构:Browser/Server&#xff0c;浏览器/服务器架构模式&#xff0c;它的特点是&#xff0c;客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务器端。浏览器只需要请求服务器&#xff0c;获取Web资源&#xff0c;服务器把Web资源…

【Leetcode】2684. 矩阵中移动的最大次数

文章目录 题目思路代码结果 题目 题目链接&#x1f517; 给你一个下标从 0 开始、大小为 m x n 的矩阵 grid &#xff0c;矩阵由若干 正 整数组成。 你可以从矩阵第一列中的 任一 单元格出发&#xff0c;按以下方式遍历 grid &#xff1a; 从单元格 (row, col) 可以移动到 (…

FPGA和ASIC

前言 大家好&#xff0c;我是jiantaoyab&#xff0c;这是我所总结作为学习的笔记第16篇,在本篇文章给大家介绍FPGA和ASIC。 一个四核i7的CPU的晶体管中有20亿的晶体管&#xff0c;需要链接起20亿的晶体管可不是一件容易的事情&#xff0c;所以设计一个CPU需要用年来算&#x…

一款博客网站源码

一款博客网站源码 源码软件库 为大家内置了主题 清爽又强大真正的永久可用的一条源码&#xff0c;该版本为整合版本&#xff0c;内置了Joe主题&#xff0c;搭建后直接启用即可~ 安装环境要求&#xff1a; PHP 7.2 以上 MySQL, PostgreSQL, SQLite 任意一种数据库支持&#xff…

MySQL基础架构

文章目录 MySQL基础架构一、连接器 - 建立连接&#xff0c;权限认证二、查缓存 - 提高效率三、分析器 - 做什么四、优化器 - 怎么做五、执行器 - 执行语句六、存储引擎1、存储引擎的概述2、存储引擎的对比3、存储引擎的命令4、存储引擎的选择 MySQL基础架构 大体来说&#xff…

Uniapp有奖猜歌游戏系统源码,附带流量主

有奖猜歌游戏是一款基于uni-app、uniCloud、uniAD 开发的小游戏&#xff0c;通过猜歌曲、观看广告赚取现金奖励。 游戏基本特征 玩家可以通过猜歌、做任务等方式直接获取现金奖励 玩家可以通过猜歌、拆红包、做任务等方式获取金币奖励&#xff0c;当金币累积到一定数量可以兑…

SLAM 算法综述

LiDAR SLAM 其主要思想是通过两个算法&#xff1a;一个高频激光里程计进行低精度的运动估计&#xff0c;即使用激光雷达做里程计计算两次扫描之间的位姿变换&#xff1b;另一个是执行低频但是高精度的建图与校正里程计&#xff0c;利用多次扫描的结果构建地图&#xff0c;细化位…

确保云原生部署中的网络安全

数字环境正在以惊人的速度发展&#xff0c;组织正在迅速采用云原生部署和现代化使用微服务和容器构建的应用程序&#xff08;通常运行在 Kubernetes 等平台上&#xff09;&#xff0c;以推动增长。 无论我们谈论可扩展性、效率还是灵活性&#xff0c;对于努力提供无与伦比的用…

<Linux> 线程的同步与互斥

目录 前言&#xff1a; 一、资源共享问题 &#xff08;一&#xff09;多线程并发访问 &#xff08;二&#xff09;临界资源与临界区 &#xff08;三&#xff09;“锁” 是什么 二、多线程抢票场景 &#xff08;一&#xff09;并发抢票 &#xff08;二&#xff09;并发访…