C++11:智能指针

智能指针,顾名思义,也就是自动回收内存的指针形式,不用程序员刻意去释放,提高软件开发效率,同时也会提高软件鲁棒性。

C++11一共有4个智能指针,分别为auto_ptr、unique_ptr、shared_ptr、weak_ptr。其中auto_ptr由于存在设计问题,被标记为“已弃用”,将在未来某个C++版本中被移除。本文主要介绍其他三个指针形式。使用前首先包含 <memory>这个头文件

1、unique_ptr

这个智能指针的含义为,智能指针所管理的内存区域为独占状态,当另一个unique_ptr访问当前指针时,当前指针会失效,内存的控制权交给新指针。示例如下:

#include <iostream>
#include <memory>
using namespace std;

void test_ptr (unique_ptr<int> p) {
}

int main (int argc, char* argv []) {
	//构造一个unique_ptr
	unique_ptr<int> p = make_unique<int> (5);
	//打印指针内容
	cout << *p << endl;
	//修改指针内容
	*p = 100;
	//打印指针内容
	cout << *p << endl;
	//将控制权交给函数参数
	test_ptr (move (p));
	//测试指针是否有效
	cout << p.get () << endl;
	return 0;
}
首先构造一个unique_ptr。unique_ptr构造方式以前一般为 unique_ptr<int> p (new int); 这样的形式,构造时直接包含一个指针。后来在C++14中引入了make_unique,建议统一写成这样的格式。
构造时设置初始值为5,打印结果也为5,然后设置指针内容为100,这儿打印出来的结果也为100,然后使用移动语义,将控制权交给test_ptr函数,这时候main函数中p指针失效,然后函数什么也不做,当它返回时,实际上已经将指针指向的内存释放了。然后我们调用 get() 函数获取智能指针管理的指针地址,打印结果为00000000

可见智能指针用法上还是很简单的。


2、shared_ptr

这是一个最像智能指针的智能指针,同时也是使用最为广泛的智能指针。示例代码如下:

#include <iostream>
#include <memory>
using namespace std;

void test_ptr (shared_ptr<int> p) {
	//显示当前引用个数
	cout << p.use_count () << endl;
}

int main (int argc, char* argv []) {
	//构造一个shared_ptr
	shared_ptr<int> p = make_shared<int> (5);
	//调用函数,增加引用计数
	test_ptr (p);
	//显示当前引用个数
	cout << p.use_count() << endl;
	//显示指针是否有效
	cout << p.get () << endl;
	return 0;
}
构造方式与unique_ptr大同小异,不过make_shared是C++11就已经存在的shared_ptr智能指针标准构造方式。

然后我们调用函数,这时候p的引用计数+1(主函数有一个引用,test_ptr函数有一个引用),打印引用数量,结果为2。函数调用完成后,智能指针引用计数-1,这时候我们再打印引用计数,结果为1。然后我们再打印地址,显示的为有效地址,可能不同电脑上地址不一样,只要不为00000000,就代表智能指针还是有效的。关于shared_ptr指针的访问方式与unique_ptr相同,这儿不再重复。

注:网神曾经说过,如果你用了智能指针,那么你也就与引用无缘了。引用不会增加引用计数。

3、weak_ptr

这个指针用于配合shared_ptr,在不增加引用计数的前提下判断shared_ptr是否有效。示例如下:

#include <iostream>
#include <memory>
using namespace std;

void test_ptr (weak_ptr<int> p) {
	//显示引用是否失效
	cout << p.expired () << endl;
	//显示当前引用个数
	cout << p.use_count () << endl;
	//通过weak_ptr构造shared_ptr
	shared_ptr<int> p2 = p.lock ();
	if (p2.get () != nullptr) {
		//显示当前引用个数
		cout << p.use_count () << endl;
	}
}

int main (int argc, char* argv []) {
	//构造一个shared_ptr
	shared_ptr<int> p = make_shared<int> (5);
	//调用函数,不增加引用计数
	test_ptr (p);
	return 0;
}
这次我们把test_ptr参数改为weak_ptr,构造它不增加引用计数。首先打印是否失效。由于main函数还存在一个引用,所以没有失效,结果为0,然后显示当前引用个数,结果为1,然后通过weak_ptr构造出shared_ptr并判断构造出的是否有效。这个判断在单线程环境下显得有些多余,不过养成良好的书写习惯非常重要。判断之后再显示出weak_ptr的引用计数,这儿的结果为2。


关于智能指针相关的概念不多,重要的是熟练运用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章