C++ primer plus学习笔记(二)——类、左值引用、右值引用、万能引用

引言

C++也是支持面向对象的语言,也有类的概念。与java差异比较大的是,没有gc(垃圾回收器),所以设计要考虑好释放,不过也提供了智能指针(自动计数引用,自动释放)。

代码风格

前面去了解vector的源码,发现大部分头文件都会使用这种方式来避免被重复导入代码

#ifndef XXX_H
#define XXX_H 1
code...
#endif

一般头文件都会这样用文件名做一个宏定义的预处理,判断是否已经被加载过这个头文件,因为宏定义是在编译阶段处理

左值与右值

左值:能出现在赋值运算左边的值
右值:只能出现在赋值运算右边的值
根据定义,左值主要是变量、常变量(const变量),而右值包括:常量、匿名对象、函数返回值

左值引用、const左值引用、右值引用

引用类型的变量的核心是其可以修改自己对应的内存空间到别的变量(修改this)而不是简单的拷贝备份
左值引用时在类型定义的右边加上&符合的引用变量,如

int a = 1;
int & b = a;
b = 5;//a == 5 为true

左值引用的变量会直接引用赋值变量,代表相同对象,但是不能引用右值,这样就会调用拷贝构造函数去复制
const左值引用就是通过const限定,允许左值引用引用右值,当是引用右值时,其会调用构造函数,生成一个临时变量存储右值,再去引用这个临时变量,这是为了避免直接使用普通变量存储时,需要执行一遍构造生成匿名对象,再执行一遍拷贝构造对变量初始化。因为被const限定,所以也无法修改,如

const int & a = 5;

而右值引用专门用来引用右值,并且没有const的修饰,所以可以进行修改,比如

int && a = 5;
a = 4;//OK

所以右值引用一般代表为临时变量/对象续命,将其转移到新的容器里去生存,所以一般也要先将旧引用的一些关联置空,因为他的成员已经由新引用接管了,避免旧引用去析构被接管的成员,造成后续右值引用在释放时重复析构。事实上其与const左值引用引用右值的区别就是,其可以对临时变量进行修改,这里推荐qicosmos(江南)的这篇博客,写的非常nice——从4行代码看右值引用

万能引用

虽然有了右值引用可以引用并修改右值,但是有时候我们传入的可能是左值,也可能是右值,所以当使用泛型的右值引用来接收时,会自动根据入值是左值还是右值,来自动转化为使用左值引用还是右值引用,这种泛型右值引用也因此被叫为万能引用。如

template <typename T> void forwardValue(T&& val){
   
		process(val);
}
template <typename T> void process(T & lVal){
   }
template <typename T> void process(T && rVal){
   }
void main(){
   
	forwardValue(1);//传入右值,val解释为右值引用
	int a = 1;
	forwardValue(a);//传入左值,val解释为左值引用
}

但是因为val是具名变量,是左值,所以无论解释为何种引用,process都走的是process(T & lVal)这个左值引用的方法。这时要使用变量原有的类型作为引用传递,需要通过std::forward来实现,std::forward函数使用变量自身的引用类型作为值去传递(底层使用static_cast强制转化),此时就会分别调用右值的process和左值的process

template <typename T> void forwardValue(T&& val){
   
		process(std::forward<T>(val));
}

类结构

与java类似,c++也是有private、public、protected等访问权限控制符,不过没有default。然后比较大区别的是,c++默认不写的访问权限是private,java是default。还有就是,C++的类没有访问权限修饰符,把对父类的访问权限放到了子类的继承方式上。同时,其成员时按照权限写到对应权限的标签后,而不是一个个控制权限。比如

	class father{
   
		int a;//private default 
	public:
		int b;
		int c;
	protected:
		int d;
	}
	
	class son:public father{
    //extends the public authority of super class
	}

从这里也看出,cpp的风格和理念和java其实相差很大,java偏向于在父类限制了程序员能够派生的子类的权限,而cpp是父类不做扩展限制,只做成员的权限划分,由派生类去决定自己要扩展到多高的访问权限。这可能也和公司有关系,java的公司oracle毕竟是搞商业的(还是要恰饭的),包括一些jdk都是收费的,所以有些高权限的代码也不想给扩展和看到。java更像工具,本身自带平台,处理好了很多东西,开发只需要关注jvm,以及他提供的给你扩展的东西,在对方为你准备好的、限制好的环境下开发,出来的东西就相对安全(bug少)。而cpp就像裸权限给你,你自己随便玩,所以很容易玩坏了(出bug)。

共享成员与对象成员

共享成员是一个类被全部对象共享的成员,即全局的、静态的、非对象独有的。像是java一样,cpp也有静态成员,但是这里用了共享成员,因为他还有另一种替代品——枚举。如下代码,是使用static和通过枚举定义类里面的静态成员的两种方式。同时,cpp限制了static成员,如果要在定义时初始化,则

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值