掘根宝典之C++类型别名,关键字typedef,auto,decltype

类型别名

在C++中,我们可以使用typedef关键字或using关键字来创建类型别名。下面是两种方式的示例:

  1. 使用typedef关键字创建类型别名:
typedef int myInt;
typedef float myFloat;myInt a;//等价int a;
myFloat b;//等价float b;

  1. 使用using关键字创建类型别名:
using myInt = int;
using myFloat = float;myInt a;//等价int a;
myFloat b;//等价float b;

使用类型别名可以方便地重命名现有的类型,以提高代码的可读性和灵活性。例如,我们可以使用以下方式创建一个类型别名来代替std::vector<int>

using IntVector = std::vector<int>;
IntVector myVector;

注意点

我们在使用类型别名的时候,要特别注意将类型别名用于指针

我们先看个例子

我们发现啊,这个第二行这句还没编译就已经显示有错误了,这是为什么呢?

这是因为遇到使用类型别名的声明语句的时候,人们总是错误的尝试把类型别名替换为它本来的样子,也就是说我们把这下面两句话视作等效的

const A b="asss";
const char*b="asss";

但是事实并不是如此。

A实际上是指向char的指针,因此,const A就是指向char的常量指针,而非指向常量字符的指针。

也就是说,下面这两句是等效的

	const A b = "asss";;char* const a = "asss";

我们再总结一下 

声明语句中用到A时,其基本数据类型是指针。

可是用char*重写了声明语句后,数据类型就变成了char,*成了声明符的一部分。这样改写的结果是,const char成了基本数据类型 

前后两种声明意义截然不同,前者声明了一个指向char的常量指针,改写后的形式则声明了一个指向const char的指针

关键字auto

在C++中,关键字auto用于自动推导变量的类型。也就是说,编译器会根据变量的初始化值来确定变量的类型。

显然auto定义的变量必须要有初始值。

定义的具体语法如下:

auto variable = value;

其中variable是变量名,value是初始化值。

例如,以下是使用auto定义变量的示例:

auto x = 10; // 推导x的类型为int,初始化为10
auto str = "Hello"; // 推导str的类型为const char*
auto vec = std::vector<int>(); // 推导vec的类型为std::vector<int>
auto sum = [](int a, int b) { return a + b; }; // 推导sum的类型为lambda表达式类型

在这些例子中,编译器会根据变量的初始化值自动推导出变量的类型,并将其赋值给相应的变量。

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

int a=9;
auto i=0,*p=&a;//正确,i是int型,p是int*型
auto b=0,c=9.0;//不正确,b和c的类型不正确

复合类型,常量和auto

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

第一点

首先,正如我们所熟知的,使用引用其实是使用引用的对象特别是当引用被用作初始值时,真正参与初始化的其实是引用对象的值。

此时编译器以引用对象的类型作为auto的类型:

int i=0,&r=i;
auto a=r;//a是一个整数(r是i的别名,而i是一个整数)

 也就是说,上面这些语句就等价于下面这个

int i=0,&r=i;
int a=i;
解决方法 

那我们怎么使用auto来用于引用呢?

很简单,直接在auto后面加一个&就行了

int i=0,&r=i;
auto &a=i;

第二点

在介绍第二点时,我们先来了解一下顶层const和底层const

顶层const表明指针本身是个常量

int* const a;

底层const表示指针指向的对象是个常量

const int*a;

接下来进入正题

 auto一般会忽略掉顶层const,同时保留底层const

什么意思呢?我们来看看一些例子

例子1
	int i = 9;const int ci = i, & cr = ci;auto b = ci;//等价int b=i;auto c = cr;//等价int c=i;

我们可能会好奇

为啥b不是const int类型?c为啥不是const int&类型?

因为ci的顶层const特性被忽略掉了 ,c也是同样的道理

如果我们需要将b,c保留顶层const特性,则需要明确指出

	int i = 9;const int ci = i, & cr = ci;const auto b = ci;//等价const int b=i;const auto c = cr;//等价const int c=i;

例子2

我们再看一个例子

int i = 9;
const int ci = i, & cr = ci;
auto d = &i;//等价int* d=&i;
auto e = &ci;//等价const int*e=&ci;

 

那为啥e就是const int*类型?

这是因为对常量对象取地址是一种底层const,会被保留下来

注意事项

以下是一些关于auto关键字的注意事项:

  1. auto只能用于自动推导变量的类型,不能用于函数的返回值、函数参数或非静态成员变量的类型。

  2. 自动推导的类型将根据变量的初始化值进行推导。如果变量的初始化值不明确或不唯一,编译器将会报错。

  3. auto关键字可以与const&等类型修饰符一起使用。例如:auto const&表示自动推导一个const引用。

  4. 当使用auto推导出的类型是一个模板类型时,编译器会根据变量的初始化值推导出具体的模板类型。

  5. 当使用auto推导出的类型是迭代器时,需要确保变量的初始化值是一个可迭代的容器,否则会导致编译错误。

  6. 自动推导类型的变量在编译时期确定类型,无法在运行时期更改类型。

总而言之,auto关键字是一个方便的特性,可以根据初始化值自动推导变量的类型,减少了显式类型声明的冗余。但需要注意,过度使用auto可能会降低代码的清晰度和可读性,所以在选择使用auto时,要谨慎权衡代码的简洁性和可读性。

关键字decltype

有的时候,我们希望从表达式的类型推断出要定义的变量的类型,但是不是想用该表达式的值初始化变量。

为了满足这种情况,C++11引入了关键字decltype,它的作用是选择并返回操作数的数据类型。在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值。

我们看个例子

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

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

换句话说,编译器为sum指定的类型是什么呢?就是假如f被调用的话将会返回的那个类型。

decltype和顶层const,引用

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 ints,y绑定到变量x
decltype(cj)z; //错误:z是一个引用,必须初始化


因为cj是一个引用,decltype(cj)的结果就是引用类型,因此作为引用的z必须被初始化。

需要指出的是,引用从来都作为其所指对象的同义词出现,只有用在decltype处是一个例外,decltype直接给一个引用类型

decltype 和引用

左右值和decltype

如果decltype使用的表达式不是一个变量,则decltype返回表达式结果对应的类型的情况有两种。

事实上,如果给decltype的表达式的结果是个左值,则decltype作用于该表达式(不是变量)得到一个引用类型。如果表达式是个右值,则直接得到对应的类型

假设p的类型是int*,因为解引用生成左值,所以decltype(*p)的结果是int&。

另一方面,因为取地址运算符生成右值,所以decltype(&p)的结果是int**,也就是说,结果是一个指向整型指针的指针。

我们再看些例子

// decltype 的结果可以是引用类型
int i=42, *p= &i, &r = i;decltype(r + 0) b; //正确:加法的结果是int,因此b是一个(未初始化的)intdecltype(*p) c; // 错误:c是int&,必须初始化


因为r是一个引用,是左值,因此decltype(r)的结果是引用类型。

如果想让结果类型是x所指的类型,可以把x作为表达式的一部分,如r+0,显然这个表达式的结果将是一个右值,所以类型是int。

 另一方面,如果表达式的内容是解引用操作,表达式是左值,则decltype 将得到引用类型。因此,decltype(*p)的结果类型就是int&,而非int。

特殊情况

有一种情况需要特别注意:对于decltype 所用的表达式来说,如果变量名加上了一对括号,则得到的类型与不加括号时会有不同。

如果decltype 使用的是一个不加括号的变量,则得到的结果就是该变量的类型;

如果给变量加上了一层或多层括号,编译器就会把它当成是一个表达式。变量是一种可以作为赋值语句左值的特殊表达式,所以这样的decltype就会得到引用类型:

// decltype的表达式如果是加上了括号的变量,结果将是引用
decltype((i)) d; /1 错误:d是int&,必须初始化
decltype(i) e; // 正确:e是一个(未初始化的)int


切记:decltype((variable))(注意是双层括号)的结果永远是引用,而 decltype(variable)结果只有当 variable 本身就是一个引用时才是引用。

decltype和auto的区别

autodecltype是C++11引入的两个关键字,用于类型推导和类型查询。它们的区别如下:

  1. auto用于自动推导变量的类型,而decltype用于获取表达式的类型。

  2. auto在编译时期根据初始化表达式推导出变量的类型,而decltype在编译时期查询表达式的类型,不会执行表达式。

  3. auto可以用于初始化变量,而decltype不能直接用于变量的初始化。

  4. auto可以推导出值类型、指针类型、引用类型等,而decltype更灵活,可以推导出表达式的类型,包括值类型、指针类型、引用类型、函数类型等。

下面是一些示例来说明它们的区别:

int x = 10;
auto a = x; // 推导出a的类型为int
decltype(x) b = x; // 查询x的类型,b的类型为intint& y = x;
auto c = y; // 推导出c的类型为int,而不是int&
decltype(y) d = y; // 查询y的类型,d的类型为int&int foo(int a, int b);
auto result = foo(1, 2); // 推导出result的类型为函数返回类型
decltype(foo(1, 2)) e = foo(1, 2); // 查询foo(1, 2)的类型,e的类型为int

总而言之,auto用于方便地推导变量的类型,而decltype用于查询表达式的类型。在实际使用中,根据需要选择合适的关键字。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

《Python深度学习》阅读笔记

以下是《Python深度学习》一书中学习过程中记录的一些重要的专属名词和概念&#xff1a; 一、概念 深度学习&#xff08;Deep Learning&#xff09;&#xff1a;指使用多层神经网络进行机器学习的技术。神经网络&#xff08;Neural Network&#xff09;&#xff1a;一种模仿生…

【Algorithms 4】算法(第4版)学习笔记 18 - 4.4 最短路径

文章目录 前言参考目录学习笔记0&#xff1a;引入介绍1&#xff1a;APIs1.1&#xff1a;API&#xff1a;加权有向边1.2&#xff1a;Java 实现&#xff1a;加权有向边1.3&#xff1a;API&#xff1a;加权有向图1.4&#xff1a;Java 实现&#xff1a;加权有向图1.5&#xff1a;AP…

【C语言】分支语句(逻辑运算符与关系运算符)

文章目录 **逻辑运算符(&&、||、!)**逻辑运算符特点短路短路-逻辑与短路-逻辑或 **关系运算符&#xff08;relational expression&#xff09;**运算操作符的结合律、运算符 **选择结构/分支结构****if 语句****复合句的if语句(if...else..语句)****不良风格的程序** *…

力扣hot100:416.分割等和子集(组合/动态规划/STL问题)

组合数问题 我们思考一下&#xff0c;如果要把数组分割成两个子集&#xff0c;并且两个子集的元素和相等&#xff0c;是否等价于在数组中寻找若干个数使之和等于所有数的一半&#xff1f;是的&#xff01; 因此我们可以想到&#xff0c;两种方式&#xff1a; ①回溯的方式找到t…

DC-DC电源管理芯片MC34063A介绍

MC34063A 为一单片 DC-DC 变换集成电路&#xff0c;内含温度补偿的参考电压源&#xff08;1.25V&#xff09;、比较器、能有效限制电流及控制工作周期的振荡器&#xff0c;驱动器及大电流输出开关管等。外配少量元件&#xff0c;就能组成升压、降压及电压反转型 DC-DC 变换器。…

计算机系统基础 2 Intel 中央处理器

Intel微处理器的发展史 INTegrated ELectronics&#xff08;集成电子&#xff09;的缩写 先后推出的中央处理器&#xff1a; Intel4004、Intel8008、Intel8080/8085、8086/8088、80186、80286、i386、i486 Pentium&#xff08;奔腾&#xff09;、Pentium II、Pentium III、Pen…

Android Studio实现内容丰富的安卓宠物用品商店管理系统

获取源码请点击文章末尾QQ名片联系&#xff0c;源码不免费&#xff0c;尊重创作&#xff0c;尊重劳动。 项目编号128 1.开发环境android stuido jdk1.8 eclipse mysql tomcat 2.功能介绍 安卓端&#xff1a; 1.注册登录 2.系统公告 3.宠物社区&#xff08;可发布宠物帖子&#…

php中 0 == ‘’(0等于任意字符串) 判断是否成立 返回true

php中不同类型变量之间比较大小 一、背景二、探究0是为什么&#xff1f;三、探究 0all是为什么&#xff1f;四、程序中如何判断0是否等于指定字符串 一、背景 最近在项目实际开发中&#xff0c;我需要判断前端传来的参数值是否等于一个字符串&#xff1b;然后发现当参数值是0时…

论文阅读——ViTAE

ViTAE: Vision Transformer Advanced by Exploring Intrinsic Inductive Bias ViTAE旨在将细胞神经网络中固有的IB引入视觉转换器。如图2所示&#xff0c;ViTAE由两种类型的细胞组成&#xff0c;即RC和NC。RC负责将多尺度上下文和局部信息嵌入到令牌中&#xff0c;NC用于进一步…

XXE漏洞原理和pikachu靶场实验

★★免责声明★★ 文章中涉及的程序(方法)可能带有攻击性&#xff0c;仅供安全研究与学习之用&#xff0c;读者将信息做其他用途&#xff0c;由Ta承担全部法律及连带责任&#xff0c;文章作者不承担任何法律及连带责任。 1、XXE漏洞原理 XXE全称&#xff1a;XML External Enti…

JUnit 面试题及答案整理,最新面试题

JUnit中的断言&#xff08;Assert&#xff09;有哪些类型&#xff1f; JUnit提供了多种断言类型来帮助测试代码的正确性。常见的断言类型包括&#xff1a; 1、assertEquals&#xff1a; 用于检查两个值是否相等。如果不相等&#xff0c;测试失败。 2、assertTrue和assertFal…

HarmonyOS NEXT应用开发—折叠屏音乐播放器方案

介绍 本示例介绍使用ArkUI中的容器组件FolderStack在折叠屏设备中实现音乐播放器场景。 效果图预览 使用说明 播放器预加载了歌曲&#xff0c;支持播放、暂停、重新播放&#xff0c;在折叠屏上&#xff0c;支持横屏悬停态下的组件自适应动态变更。 实现思路 采用MVVM模式进…

【消息队列开发】 实现消息垃圾回收

文章目录 &#x1f343;前言&#x1f38b;准备工作&#x1f38d;具体实现&#x1f6a9;创建一个新文件&#x1f6a9;读取有效对象&#x1f6a9;把有效消息写入新文件中&#x1f6a9;以旧换新&#x1f6a9;更新统计文件&#x1f6a9;特别注意&#x1f6a9;完整代码 ⭕总结 &…

2.1_5 数据交换方式

文章目录 2.1_5 数据交换方式&#xff08;一&#xff09;为什么要数据交换&#xff1f;&#xff08;二&#xff09;数据交换方式&#xff08;1&#xff09;电路交换&#xff08;Circuit Exchanging&#xff09;&#xff08;2&#xff09;报文交换&#xff08;Message Exchangin…

mybatis源码阅读系列(二)

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

环形链表2(C++), test ok

1. 题目 2. 思路分析&#xff1a; 与环形链表1一样&#xff0c;我们需要定义慢指针和快指针&#xff0c;确定链表是否有环&#xff0c;如果链表没有环的话&#xff0c;直接置空即可。如果链表有环&#xff0c;则需要向环形链表1一样&#xff0c;让快指针不断追赶慢指针&#x…

NVENC 视频编码器 API 编程指南 ( 中文转译 )

基于 NVIDIA Kepler™ 和更高版本 GPU 架构的 NVIDIA GPU 包含基于硬件的 H.264/HEVC/AV1 视频编码器&#xff08;以下简称 NVENC&#xff09;。NVENC 硬件采用 YUV/RGB 作为输入&#xff0c;并生成符合H.264/HEVC/AV1 标准的视频比特流。可以使用 NVIDIA 视频编解码器 SDK 中提…

Learn OpenGL 15 面剔除

面剔除 尝试在脑子中想象一个3D立方体&#xff0c;数数你从任意方向最多能同时看到几个面。如果你的想象力不是过于丰富了&#xff0c;你应该能得出最大的面数是3。你可以从任意位置和任意方向看向这个球体&#xff0c;但你永远不能看到3个以上的面。所以我们为什么要浪费时间…

Avalonia学习1:下载通用皮肤SukiUI,并在windows上启动成功

目录 1、引言 2、碰到的问题 1、下载下拉VS2022老版本的用不了。 2、升级后&#xff0c;发现没有装wsl&#xff0c;导致启动不了&#xff0c;但wsl又由于国内的关系安装不了&#xff0c;怎么办呢&#xff0c; 1、引言 最近在想有没有什么可以开发在Linux下运行…

公众号留言功能恢复了,你的开通了吗?

了解公众号的人都知道&#xff0c;腾讯在2018年3月宣布暂停新注册公众号的留言功能&#xff0c;这之后注册的公众号都不具备留言功能。 这成了很多号主运营人的一块心病&#xff0c;也包括我。 没有留言&#xff0c;就好似一个人玩单机游戏&#xff0c;无法与读者互动&#xff…