13C++11提高类型安全.md

1. 强类型枚举
//c++11的强类型枚举可以指定底层基于的基本类型,我们可以避免编译器不同而带来的不可移植性。
//另外,设置较小的基本类型也可以节省内存空间。
enum  class C : char {C1 = 1, C2 = 2};
enum class D : unsigned int {D1 = 1, D2 = 2, Dbig = 0xFFFFFFF0U};
cout << "sizeof(C):" << sizeof(C) << endl;			//1
cout << "sizeof(C::C1):" << sizeof(C::C1) << endl;	//1
cout << "sizeof(D::D1)" << sizeof(D::D1) << endl;	//4
2. 堆内存管理:智能指针与垃圾回收
2.1 显式内存管理

​ 从语言层面来讲,c++中内存相关的问题可以归纳为三个方面。

  • 野指针:一些内存单元已被释放,之前指向它的指针却还在被使用。这些内存有可能被运行时系统重新分配给程序使用,从而导致了无法预测的错误。
  • 重复释放:程序试图去释放已经被释放过的内存单元,或者释放已经被重新分配过的内存单元,就会导致重复释放错误。通常重复释放内存会导致 c/c++ 运行时系统打印出大量错误及诊断信息。
  • 内存泄漏:不再需要使用的内存单元如果没有被释放就会导致内存泄漏。如果程序不断重复进行这类操作,将会导致内存占用剧增。
2.2. C++11 智能指针
void testUniquePtr()
{
cout << "enter testUniquePtr()...................................................................." << endl;
	unique_ptr<int> up1(new int(1));
	//unique_ptr<int> up2 = up1;		//编译失败,unique_ptr所指对象的内存的所有权只能通过标准库的 move 函数来转移
	unique_ptr<int> up2 = move(up1);	//up2是数据唯一的 unique_ptr 智能指针
	cout << "*up2:" << *up2 << endl;
	unique_ptr<int> up3(move(up2));
	cout << "*up3:" << *up3 << endl;
	up1.reset();
	up2.reset();
	up3.reset();
	cout << "return from testUniquePtr()...................................................................." << endl;
}

​ 从实现上讲, unique_ptr 是一个删除了拷贝构造函数、保留了移动构造函数的指针封装类型。程序员仅可以使用右值对 unique_ptr 对象进行构造,而且一旦构造成功,右值对象中的指针即被“窃取”,因此该右值对象即刻失去了对指针的“所有权”。

shared_ptr<int> sp1(new int(22));
shared_ptr<int> sp2 = sp1;
auto sp3 = sp1;
cout << "*sp1:" << *sp1 << endl;	//22
cout << "*sp2:" << *sp2 << endl;	//22
sp1.reset();
cout << "*sp2:" << *sp2 << endl;	//22
cout << "*sp3:" << *sp3 << endl;	//22
sp2.reset();
cout << "*sp3:" << *sp3 << endl;	//22

​ 而 shared_ptr 同样形如其名,允许多个该智能指针共享地“拥有”同一堆分配对象的内存。与 unique_ptr 不同的是,由于在事项上采用了引用计数,所以一旦一个 shard_ptr 指针放弃了“所有权”,其他的 shared_ptr 对对象内存的引用并不会受影响。某个智能指针调用 reset 知会导致引用计数的降低,不会导致堆内存的释放。

2.3 垃圾回收的分类

​ 我们把之前使用过,现在不再使用或者没有任何指针再指向的内存空间就称为 “垃圾”。而将这些 “垃圾”收集起来以便再次利用的机制,就被称为“垃圾回收”。

​ 在当前流行的编程语言中,除过 c 和 Pascal 不支持,c++ 部分支持外,其他语言大多都支持自动回收。

​ 垃圾回收的方式虽然很多,但主要可以分为两大类:

(1)基于引用计数的垃圾回收器

​ 简单地说,引用计数主要是使用系统记录对象被引用(引用、指针)的次数。当对象被引用的次数变为 0 时,该对象即被视作 “垃圾”而回收。使用引用计数做垃圾回收的算法的一个优点是实现很简单,与其他垃圾回收算法相比,该方法不会造成程序暂停,因为技术的增减与对象的使用是紧密结合的。此外,引用计数也不会对系统的缓存或者交换空间赞成冲击,因此被认为“副作用”较小。但是这种方法比较难处理“环形引用”问题,此外由于技术带来的额外开销也并不小,所以在使用上也有一定的限制。

(2)基于跟踪处理的垃圾回收器

​ 相比于引用计数,跟踪处理的垃圾回收机制被更广泛地引用。器基本方法是产生跟踪对象的关系图,然后进行垃圾回收。使用跟踪方式的垃圾回收算法主要有以下几种:

  • 标记-清除
  • 标记-整理
  • 标记-拷贝
2.4 c++ 与垃圾回收

​ 指针的灵活性使用可能是 c/c++ 中的一大优势,而对于垃圾回收来说,却会带来很大的困扰。

posted @ 2020-08-01 17:10  洛克十年  阅读(124)  评论(0编辑  收藏  举报