掘根宝典之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://www.rhkb.cn/news/276638.html

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

相关文章

Python面向对象构造函数:手把手教你如何玩转对象初始化

我们都知道&#xff0c;Python是一个面向对象的语言&#xff0c;这意味着我们可以用类来定义对象的属性和方法。而构造函数&#xff0c;就是当我们创建一个新的对象时&#xff0c;会自动调用的特殊方法。那么&#xff0c;如何玩转这个构造函数呢&#xff1f; 首先&#xff0c;…

YoloV8改进策略:下采样改进|HWD改进下采样

摘要 本文使用HWD改进下采样&#xff0c;在YoloV8的测试中实现涨点。 论文解读 在卷积神经网络&#xff08;CNNs&#xff09;中&#xff0c;极大池化或跨行卷积等下采样操作被广泛用于聚合局部特征、扩大感受野和最小化计算开销。然而&#xff0c;对于语义分割任务&#xff…

golang中new和make的区别

1. 先看一个例子 package mainimport "fmt"func main() {var a *int*a 10fmt.Println(*a) }运行结果是啥呢&#xff1f; 问&#xff1a;为什么会报这个panic呢&#xff1f; 答&#xff1a;因为如果是一个引用类型&#xff0c;我们不仅要声明它&#xff0c;还要为…

MySQL 压测与结果分析

文章目录 说明1. 安装部署1.1 二进制包1.2 源码包 2. 服务器性能测试2.1 CPU2.2 内存2.3 磁盘 3. MySQL 基准测试3.1 参数解析3.2 压测命令3.3 输出解读3.4 结果分析 说明 Sysbench 是一个开源的多线程基准测试工具&#xff0c;也是目前使用最多的 MySQL 压力测试工具。本篇文…

JVM是如何运行的

JVM&#xff08;Java Virtual Machine&#xff0c;Java虚拟机&#xff09;是 Java 程序的运行环境&#xff0c;它负责将 Java 字节码翻译成机器代码并执行。也就是说 Java 代码之所以能够运行&#xff0c;主要是依靠 JVM 来实现的。 JVM 整体的大概执行流程是这样的&#xff1…

Android cmdline tools安装

打开AS 进入SDK Tools 看到了吗?那个打着勾的就是

Centos8安装Docker,使用阿里云源

一、前期准备 1.关闭防火墙&#xff0c;SELINUX systemctl stop firewalld.service systemctl disable firewalld.service setenforce 0 sed -i "s/SELINUXenforcing/SELINUXdisabled/g" /etc/selinux/config查看状态 systemctl status firewalld systemctl status…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:NavRouter)

导航组件&#xff0c;默认提供点击响应处理&#xff0c;不需要开发者自定义点击事件逻辑。 说明&#xff1a; 该组件从API Version 9开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 必须包含两个子组件&#xff0c;其中第二个子组…

c++入门你需要知道的知识点(上)

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 今日主菜&#xff1a;c入门 主厨&#xff1a;邪王真眼 所属专栏&#xff1a;c专栏 主厨的主页&#xff1a;Chef‘s blog 前言&#xff1a; 咱也是好久没有更…

大数据与云计算

目录 一、大数据时代二、云计算——大数据的计算三、云计算发展现状四、云计算实现机制五、云计算压倒性的成本优势 一、大数据时代 我们先来看看百度关于 “大数据”&#xff08;Big Data&#xff09;的搜索指数。 可以看出&#xff0c;“大数据” 这个词是从2012年才引起关注…

flask-sqlalchemy库

彩笔激流勇退。 1. 简介 ORM&#xff0c;对象关系映射。简单来说&#xff0c;ORM将数据库中的表与面向对象中的类建立了一种对应关系。这样&#xff0c;我们要操作数据库&#xff0c;表&#xff0c;记录就可以直接通过操作类或者类实例来完成。 SQLAlchemy 是目前python中最…

面向对象编程第二式:继承 (Java篇)

本篇会加入个人的所谓‘鱼式疯言’ ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

【Golang】golang使用三方SDK操作容器指南

【Golang】golang使用三方SDK操作容器指南 大家好 我是寸铁&#x1f44a; 总结了一篇 golang使用三方SDK操作容器✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 这应该是目前全网最全golang使用三方SDK操作容器的指南了✌️ CreateConfig 主要是创建容器的配置信息&#xff0c;常…

uniapp遇到的问题

【uniapp】小程序中input输入框的placeholder-class不生效解决办法 解决&#xff1a;写在scope外面 uniapp设置底部导航 引用&#xff1a;https://www.jianshu.com/p/738dd51a0162 【微信小程序】moveable-view / moveable-area的使用 https://blog.csdn.net/qq_36901092/…

【机器学习】走进监督学习:构建智能预测模型的第一步

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;机器学习 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…

go语言基础笔记

1.基本类型 1.1. 基本类型 bool int: int8, int16, int32(rune), int64 uint: uint8(byte), uint16, uint32, uint64 float32, float64 string 复数&#xff1a;complex64, complex128 复数有实部和虚部&#xff0c;complex64的实部和虚部为32位&#xff0c;complex128的实部…

基于Java+SpringBoot+vue+element实现校园闲置物品交易网站

基于JavaSpringBootvueelement实现校园闲置物品交易网站 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 ** 作者主页 央顺技术团队** 欢迎点赞 收藏 ⭐留言 文末获取源码联系方式 文章目录 基于…

【Unity】Tag、Layer、LayerMask

文章目录 层&#xff08;Layer&#xff09;什么是LayerLayer的应用场景Layer层的配置&#xff08;Tags & Layers&#xff09;Layer的数据结构LayerMaskLayer的选中和忽略Layer的管理&#xff08;架构思路&#xff09;层碰撞矩阵设置&#xff08;Layer Collision Matrix&…

人工智能入门学习笔记1:什么是人工智能

一、什么是人工智能 人工智能(Artificial Intelligence)&#xff0c;是一个以计算机科学&#xff08;Computer Science&#xff09;为基础&#xff0c;由计算机、心理学、哲学等多学科交叉融合的交叉学科、新兴学科&#xff0c;研究、开发用于模拟、延伸和扩展人的智能的理论、…

【探索程序员职业赛道:挑战与机遇】

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…