Re 从零开始的C++之路(二)const和类型处理

本文详细解析了C++中的const限定符对于复合类型、指针及引用的影响,并介绍了如何利用autodecltypeusing等关键字简化复杂类型的声明与使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一节写了一些c++基本的变量的一些知识。这一节针对const限定符对于符合类型指针和引用的影响做了细致的学习。

后面加上了利用auto decltype using等关键字对复杂类型和类型的推导做了一些描述。另外,极客学院的C++课程听了真的想让人睡觉,而且几乎就是照搬《C++Primer》。学习这种基础的课程还是推荐从书本上学习,昨晚听的那个老师的声音着实让我反胃。嘿嘿。

1.const限定符

有的时候我们需要一个不会改变自身值的变量,也就是常量。
比如我们需要一块固定大小的内存空间,可以把这个值赋值给一个常量。
可以使用const限定符来限定一个变量。
const int room = 1000;
这里room 就是一个整型的常量了。任何修改这个常量的行为都是不合法的。
例如 
room = 25;
同样的 这样的常量必须要赋予初试值。因为以后不能改变这个值,所以必须有初始值。
在使用时const对象仅仅限制了改变自身值的场合,别的使用方式和非const对象一样。


2.const对象的作用域
一般来说const对象仅仅在所定义的文件内部有效。
因为编译器对于常量对象在编译的时候就把对应位置的常量替换成相应的字面值。
所以编译器需要在开始之前就知道const对象的值,也就是说它只能找到目前文件里的值
像之前提过的声明 采用extern关键字可以让声明扩展到多个文件。
extern int room = 1000;
extern int room;
对于const对象不管是定义还是声明都是用extern关键字,这样可以省去很多烦恼。


3.const对象的引用
const对象和其他对象一样,也可以存在引用的。称之为对常量的引用。
这种绑定的引用是不能用来改变常量的值的。
const int t = 2000;
const int &y = t;//需要引用和引用的对象都是常量
y = 12;//错误 无法使用常量引用改变常量
int &x = t;//错误无法使用非常量引用绑定常量


4.对const的引用和初始化
一般来说 引用必须和所引用的对象的类型保持一致。但是存在特殊情况,
对常量的引用可以使用表达式作为右值。比如,
const int &t = 2*18;
在这里,其实相当于编译器申请了一个常量变量,然后再绑定。上述代码等价于,
const int temp = 2*18;
const int &t = temp;
但是注意到这里的temp是系统自己申请的,我们无法找到,以后也只能通过这个引用找到这个常量。


在初始化的时候,如果初始值并不满足常量引用类型,就会发生如下的情况。
double d = 3.14;
const int &t = d;


但是实际上,d是双精度浮点数,而t是对整型常量的引用,所以,
double d = 3.14;
const int temp = d;
const int &t = temp;
这里可以看到最后绑定的并不是d而是系统临时生成的temp。


由此可以看出,对常量的引用并不一定要求被绑定的变量是常量。所以常量引用其实代表了仅仅限制利用这个引用修改这个被绑定对象的值。仍然可以通过其他手段改变被绑定对象的值。


5.const和指针
存在const引用,自然也存在指向const的指针
const double t = 3.14;
const double *p = t;
这里和引用的作用一样 通过这个指针p无法修改t的值。
和引用相似,允许常量指针指向非常量对象。只是不能通过这个指针修改指向对象的值。


上面说的是指向常量的指针下面要介绍const指针。两者是不同的。
指向常量的指针字面上理解的是,不能指针指向的是一个常量。既然是常量就不能修改,但是这里其实常量是假的,因为就算指向的是非常量也仅仅是说不能通过这个指针改变对象的值。


至于const指针,由于指针和引用不同,指针本身就是个对象。所以可以改变自己的值。但是这里的const指针是指那些不能改变自身值的指针。即是指指针本身就是常量。


double t = 3.14;
double *const p = &t;
表达式最好从右往左理解。p首先是const是常量。然后是*是指针。然后是指向double类型的指针。
将指向常量的指针和const指针联系在一起。
const double t = 3.14;
const double *const p = &t;
这里p自己是一个常量,定义了以后就不能改变值。然后它是一个指向常量的指针,无法通过p改变t的值。 


6.顶层const 和 底层const
我们将const分为顶层和底层。通俗的讲,顶层const相当于这个变量本身就是常量。相当于const 指针。
或者 const int t = 3;这些变量的值无法修改。所以顶层const适用于所有类型的变量。
而底层const 是指符合类型,也就是指针和引用。是说这个指针和引用所指向和绑定的变量是一个常量。
const double *p = nullpter;//这里是底层const.是说nullpter是一个常量。
const double *const p = nullpter;//这里右侧的const是顶层const,说明p是一个常量。左侧的const是底层const,即p所指向的对象nullpter是常量。
在执行拷贝操作的时候,顶层const是可以被忽略的。而底层const是不能忽略的。
比如对于
const double t = 3.14;
const double *const p = &t;
const double *pi = p;//这里顶层const被忽略了。而底层的const依然会保留


7.常量表达式
常量表达式是指那些在编译前就可以得到的值的表达式。在某些大型的工程中由于数据的复杂性,我们没法的值到底这个表达式是不是常量表达式。在C++中可以利用constexpr来判断。
设表达式是a*b*c
那么如果 
constexpr int exp = a * b * c;
如果不报错就证明表达式是常量表达式。
前面所讲到的所有数据类型都属于字面值常量。自定义类型、IO库、string类型不是字面值类型,不能被定义为constexpr变量。


8.类型的处理
有的时候东西多了,变量或者别的表示符的数量和名字长度就会变得特别的复杂。所以可以使用类型别名给标识符起别的方便的名字。


typedef double wages;//wages 是double的别名
typedef wages base;//定义了一个double类型的变量base
这里我要吐槽一下 加上typedef我觉得反而闹心了 感觉傻傻的


在新标准C++11中可以采用using
using SI = trr;
可以直接用 SI y;
等价于 trr y;
这就方便多了嘛。


9.auto 类型
变量的类型要满足变量的值。有时候右值很复杂所以可以利用auto来推测左值类型。
auto item = a + b;//根据a+b推算左值类型。
auto p = 3,r = 3.14;//这里p 和 r 类型不一致所以不行
int i = 0,&r = i;
auto a = r;
这里虽然用引用r来初始化,但是等价于被绑定的变量类型 所以 auto 这里是整型,不是整型引用。
其次 auto 也会忽略顶层const 这里的原理和拷贝复制一样,尽管你是常量但是你本身还是一个类型值,所以(编译器自然不会鸟你的个性,2333)。不过底层const 是无法忽略的。
如果你希望推导出来的auto 是顶层const的那就自己动手吧。
const auto p = i;
还有注意一点,也是经常容易忽略的一点,* 和 & 在声明和定义的时候一定是紧贴标识符的,和类型名无关。
比如 double p1,*p2;
p1是double p2是指向double类型的指针。


10.decltype类型指示符
如果仅仅想知道变量的类型,不想用表达式的值进行初始化,便可利用decltype.
int ci = 4;
decltype(ci) p = 5;//这里 p使用的ci的类型 int
但是 如果 ci 是变量 那么返回的就是变量类型,如果ci 是一个引用类型 那么返回的也就是个引用类型。
对于如下代码 
int a = 3;
int &b = a;
decltype(b) c;//显然不对 因为b是引用类型 引用定义必须初始化
那么
decltype(b+0) c;//这里就正确了 因为 b+0就是表达式了 这个表达式的类型就是c的类型 不是引用。
另一方面 如果 表达式的类型是解引用类型,那么decltype(*p) 将得到的是p所指向的对象的引用类型。
还有一点 
如果 
decltype((i))那么得到的将是i的引用类型。即如果i是引用那么得到的也是引用,如果i是变量那么得到的将是变量的引用。


11.自定义数据类型
终于有一点面向对象的味道了。C++的强大在于用户自己定义属于自己的数据类型。
将不同的数据组织在一起形成新的类型的过程也就是定义自定义数据类型的过程。
struct s
{
int s1;
int s2;
int s3;
};
这里定义了一个新的类型s里面的数据是s1,s2,s3.就是C语言中经典的结构体。
但是C++中称之为类 里面的s1,s2,s3称为类成员。一般分为数据成员和函数成员(大致就是这个意思)。
使用类成员时,以上面的s为例
s m,*p;
p = &m;
s是类型名,m是s类的对象,p是指向m的指针。
如果想得到m里的s1则可以

m.s1 或者 p->s1 

好了第二篇文章就这么搞定了。坐在电脑前3个小时了休息一下,下午试试看能不能开一篇关于OpenCV的。

基于数据挖掘的音乐推荐系统设计与实现 需要一个代码说明,不需要论文 采用python语言,django框架,mysql数据库开发 编程环境:pycharm,mysql8.0 系统分为前台+后台模式开发 网站前台: 用户注册, 登录 搜索音乐,音乐欣赏(可以在线进行播放) 用户登陆时选择相关感兴趣的音乐风格 音乐收藏 音乐推荐算法:(重点) 本课题需要大量用户行为(如播放记录、收藏列表)、音乐特征(如音频特征、歌曲元数据)等数据 (1)根据用户之间相似性或关联性,给一个用户推荐与其相似或有关联的其他用户所感兴趣的音乐; (2)根据音乐之间的相似性或关联性,给一个用户推荐与其感兴趣的音乐相似或有关联的其他音乐。 基于用户的推荐基于物品的推荐 其中基于用户的推荐是基于用户的相似度找出相似相似用户,然后向目标用户推荐其相似用户喜欢的东西(你类似的人也喜欢**东西); 而基于物品的推荐是基于物品的相似度找出相似的物品做推荐(喜欢该音乐的人还喜欢了**音乐); 管理员 管理员信息管理 注册用户管理,审核 音乐爬虫(爬虫方式爬取网站音乐数据) 音乐信息管理(上传歌曲MP3,以便前台播放) 音乐收藏管理 用户 用户资料修改 我的音乐收藏 完整前后端源码,部署后可正常运行! 环境说明 开发语言:python后端 python版本:3.7 数据库:mysql 5.7+ 数据库工具:Navicat11+ 开发软件:pycharm
MPU6050是一款广泛应用在无人机、机器人运动设备中的六轴姿态传感器,它集成了三轴陀螺仪三轴加速度计。这款传感器能够实时监测并提供设备的角速度线性加速度数据,对于理解物体的动态运动状态至关重要。在Arduino平台上,通过特定的库文件可以方便地与MPU6050进行通信,获取并解析传感器数据。 `MPU6050.cpp``MPU6050.h`是Arduino库的关键组成部分。`MPU6050.h`是头文件,包含了定义传感器接口函数声明。它定义了类`MPU6050`,该类包含了初始化传感器、读取数据等方法。例如,`begin()`函数用于设置传感器的工作模式I2C地址,`getAcceleration()``getGyroscope()`则分别用于获取加速度角速度数据。 在Arduino项目中,首先需要包含`MPU6050.h`头文件,然后创建`MPU6050`对象,并调用`begin()`函数初始化传感器。之后,可以通过循环调用`getAcceleration()``getGyroscope()`来不断更新传感器读数。为了处理这些原始数据,通常还需要进行校准滤波,以消除噪声漂移。 I2C通信协议是MPU6050与Arduino交互的基础,它是一种低引脚数的串行通信协议,允许多个设备共享一对数据线。Arduino板上的Wire库提供了I2C通信的底层支持,使得用户无需深入了解通信细节,就能方便地与MPU6050交互。 MPU6050传感器的数据包括加速度(X、Y、Z轴)角速度(同样为X、Y、Z轴)。加速度数据可以用来计算物体的静态位置动态运动,而角速度数据则能反映物体转动的速度。结合这两个数据,可以进一步计算出物体的姿态(如角度角速度变化)。 在嵌入式开发领域,特别是使用STM32微控制器时,也可以找到类似的库来驱动MPU6050。STM32通常具有更强大的处理能力更多的GPIO口,可以实现更复杂的控制算法。然而,基本的传感器操作流程数据处理原理与Arduino平台相似。 在实际应用中,除了基本的传感器读取,还可能涉及到温度补偿、低功耗模式设置、DMP(数字运动处理器)功能的利用等高级特性。DMP可以帮助处理传感器数据,实现更高级的运动估计,减轻主控制器的计算负担。 MPU6050是一个强大的六轴传感器,广泛应用于各种需要实时运动追踪的项目中。通过 Arduino 或 STM32 的库文件,开发者可以轻松地与传感器交互,获取并处理数据,实现各种创新应用。博客其他开源资源是学习解决问题的重要途径,通过这些资源,开发者可以获得关于MPU6050的详细信息实践指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值