智能指针,顾名思义,也就是自动回收内存的指针形式,不用程序员刻意去释放,提高软件开发效率,同时也会提高软件鲁棒性。
C++11一共有4个智能指针,分别为auto_ptr、unique_ptr、shared_ptr、weak_ptr。其中auto_ptr由于存在设计问题,被标记为“已弃用”,将在未来某个C++版本中被移除。本文主要介绍其他三个指针形式。使用前首先包含
1、unique_ptr
这个智能指针的含义为,智能指针所管理的内存区域为独占状态,当另一个unique_ptr访问当前指针时,当前指针会失效,内存的控制权交给新指针。示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #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><int> p = make_unique</int><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
构造时设置初始值为5,打印结果也为5,然后设置指针内容为100,这儿打印出来的结果也为100,然后使用移动语义,将控制权交给test_ptr函数,这时候main函数中p指针失效,然后函数什么也不做,当它返回时,实际上已经将指针指向的内存释放了。然后我们调用 get() 函数获取智能指针管理的指针地址,打印结果为00000000
可见智能指针用法上还是很简单的。
2、shared_ptr
这是一个最像智能指针的智能指针,同时也是使用最为广泛的智能指针。示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #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是否有效。示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #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。
关于智能指针相关的概念不多,重要的是熟练运用。