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

news2024/12/28 6:23:29

类型别名

在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;

第二点

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 的结果可以是引用类型
int i=42, *p= &i, &r = i;

decltype(r + 0) b; //正确:加法的结果是int,因此b是一个(未初始化的)int

decltype(*p) c; // 错误:c是int&,必须初始化


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

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

另一方面,如果表达式的内容是解引用操作,则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的类型为int

int& 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.coloradmin.cn/o/1509028.html

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

相关文章

4、Generator、class类、继承、Set、Map、Promise

一、生成器函数Generator 1、声明generator函数 function* 函数名() { }调用生成器函数 需要next()返回一个generator对象&#xff0c;对象的原型上有一个next(),调用返回对象{value:yield后面的值,done} function* fn() {console.log("我是生成器函数") } let it…

B端系统:漂亮就行。扯淡,漂亮仅占五分之一!

Hi&#xff0c;我是贝格前端工场&#xff0c;接触N多B端系统&#xff0c;也优化升级过N多。在这个过程中&#xff0c;仅仅美观是不够的&#xff0c;所以我拓展出来的B端系统五度评价指标&#xff0c;本篇着重讲易用性指标&#xff0c;欢迎老铁们评论点赞转发&#xff0c;有需求…

crossover玩不了qq游戏大厅怎么办 仍有五亿人坚持用QQ crossover玩游戏 Mac电脑玩QQ游戏

从1999年2月&#xff0c;QQ首个版本QICQ&#xff08;OPEN-ICQ&#xff09;上线。到2024年&#xff0c;靠着5亿月活用户&#xff0c;守住社交领域TOP2位置。你还记得QQ经典的铃声吗&#xff1f; 根据月狐数据2023年12月的统计&#xff0c;QQ月活跃账户数比微博和知乎加在一起还要…

安防视频监控汇聚平台EasyCVR使用RTMP推流出现异常的原因排查与解决

AI视频智能分析/视频监控管理平台EasyCVR能在复杂的网络环境中&#xff08;专网、内网、局域网、广域网、公网等&#xff09;&#xff0c;支持设备通过4G、5G、WIFI、有线等方式接入&#xff0c;并将设备进行统一集中接入与视频汇聚管理&#xff0c;经平台接入的视频流能实现多…

paddle的版面分析的环境搭建及使用

一、什么是版面分析 版面分析技术&#xff0c;主要是对图片形式的文档进行版面分析&#xff0c;将文档划分为文字、标题、表格、图片以及列表5类区域&#xff0c;如下图所示&#xff1a; 二、应用场景 2.1 合同比对 2.2 文本类型划分 2.3 通用文档的还原 版面分析技术可将以…

KIF本地密钥注入验证步骤 RSA加解密 python JAVA

**验证步骤&#xff1a;** # 终端随机生成一对RSA key pair pem文件 # 终端把sn及公钥发过去 # KIF返回公钥加密后的IPEK及明文IPEK的KCV &#xff08;加密机处理加密等操作&#xff1a;把sn和Base Derivation Key分散生成IPEK用加密机的Local Master Key存入加密机&#xff0c…

『运维备忘录』之 iptables 防火墙使用指南

前言 iptables 是一个配置 Linux 内核防火墙的命令行工具&#xff0c;它是用来设置、维护和检查Linux内核的IP包过滤规则的。本文将介绍 iptables 的基础知识和使用示例。 注意&#xff1a;红帽/红旗/CentOS等 7 版本以上已改为使用 firewalld 作为防火墙替换iptables。 一、基…

AIGC: 2 语音转换新纪元-Whisper技术在全球客服领域的创新运用

背景 现实世界&#xff0c;人跟人的沟通相当一部分是语音沟通&#xff0c;比如打电话&#xff0c;聊天中发送语音消息。 而在程序的世界&#xff0c;大部分以处理字符串为主。 所以&#xff0c;把语音转换成文字就成为了编程世界非常普遍的需求。 Whisper 是由 OpenAI 开发…

3.11_C++_day1_作业

作业要求&#xff1a; 程序代码&#xff1a; #include <iostream> #include <string.h>using namespace std;int main() {int a0,b0,c0,d0,e0;//分别记录字符串中的大写&#xff0c;小写&#xff0c;数字&#xff0c;空格&#xff0c;其他字符个数string str;cha…

AHU 汇编 实验五

实验名称&#xff1a;实验五 分支与循环程序设计 二、实验内容&#xff1a;从键盘输入一个四位的16进制数&#xff08;其中字母为大写&#xff09;&#xff0c;将其转化为二进制数提示输出。 实验过程&#xff1a; 源代码: data segmentbuff1 db Please input a number(H):$b…

03:HAL---中断

目录 一:中断 1:简历 2:AFIO 3:EXTI 4:NVIC基本结构 5:使用步骤 6:设计中断函数 二:中断的应用 A:对外式红外传感计数器 1:硬件介绍 2:计数代码 B:旋转编码计数器 1:硬件介绍 2:旋转编码器代码 C:按键控制LED D:代码总结 一:中断 1:简历 中断&#xff1a;在主程序…

UI学习 一

教程&#xff1a;Accessibility – Material Design 3 需要科学上网&#xff0c;否则图片显示不出来。设计教程没有图片说明&#xff0c;不容易理解。 优化UI方向 清晰可见的元素足够的对比度和尺寸重要性的明确等级一眼就能辨别的关键信息 传达某一事物的相对重要性 将重…

Unity项目开发必备技能——字体替换工具的使用(上)

在平常我们做unity项目的时候&#xff0c;工具类的使用对于我们来说是必不可少的组成部分&#xff0c;因为工具类可以解决实际问题或者是优化我们已经实现的功能。 当你在做项目的时&#xff0c;我们搭建完场景后&#xff0c;当前场景中你所创建的UI组件中的Text的字体&#xf…

springboot+vue3+nuxt3+ts+minio开发的dsblog3.0前后端分离博客

springbootvue3nuxt3tsminio开发的dsblog3.0前后端博客 一、技术栈 本博客系统采用了先进且成熟的技术栈&#xff0c;包括Spring Boot 3、Spring Security、Vue 3、Nuxt 3、TypeScript、Vite、MinIO、Redis、Element Plus和Markdown等。这些技术共同协作&#xff0c;确保了博…

float32 float16 bfloat16 推理训练GPU速度和内存调研

概念&#xff1a; 参考&#xff1a;Accelerating Large Language Models with Mixed-Precision Techniques - Lightning AI 3种数量类型表示的数据范围不一样&#xff0c;以float32为例其中有1个符号位&#xff0c;8位表示指数&#xff0c;23位表示尾数 标准训练推理是用的fl…

力扣大厂热门面试算法题 15-17

15. 三数之和&#xff0c;16. 最接近的三数之和&#xff0c;17. 电话号码的字母组合&#xff0c;每题做详细思路梳理&#xff0c;配套Python&Java双语代码&#xff0c; 2024.03.11 可通过leetcode所有测试用例。 目录 15. 三数之和 解题思路 完整代码 Java Python ​…

解锁App推广新姿势:Xinstall专属二维码,让推广更高效!

在移动互联网时代&#xff0c;App推广的重要性不言而喻。然而&#xff0c;推广的过程中往往伴随着各种痛点&#xff0c;如何准确追踪用户来源、如何提高安装转化率等&#xff0c;一直是广告主和开发者们关注的焦点。今天&#xff0c;我们要为大家介绍一款专业的App全渠道统计服…

Java基于SpringBoot+Vue的人事管理系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

Linux——文件缓冲区与模拟实现stdio.h

前言 我们学习了系统层面上的文件操作&#xff0c;也明白了重定向的基本原理&#xff0c;在重定向中&#xff0c;我们使用fflush(stdout)刷新了缓冲区&#xff0c;当时我们仅仅知道重定向需要刷新缓冲区&#xff0c;但是不知道其所以然&#xff0c;今天我们来见识一下。 一、…

vue自定义主题皮肤方案

方案一&#xff1a;CSS变量换肤&#xff08;推荐&#xff09; 利用css定义变量的方法&#xff0c;用var在全局定义颜色变量&#xff08;需将变量提升到全局即伪类选择器 :root&#xff09;然后利用js操作css变量&#xff0c;document.getElementsByTagName(‘body’)[0].style…