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

上一节写了一些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的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的公寓报修管理系统,源码+数据库+毕业论文+视频演示 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本公寓报修管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此公寓报修管理系统利用当下成熟完善的Spring Boot框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。公寓报修管理系统有管理员,住户,维修人员。管理员可以管理住户信息和维修人员信息,可以审核维修人员的请假信息,住户可以申请维修,可以对维修结果评价,维修人员负责住户提交的维修信息,也可以请假。公寓报修管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 关键词:公寓报修管理系统;Spring Boot框架;MySQL;自动化;VUE
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值