C++中的shared_ptr和weak_ptr
Posted weihao-ysgs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++中的shared_ptr和weak_ptr相关的知识,希望对你有一定的参考价值。
shared_ptr 和 weak_ptr
shared_ptr
相关特性
-
引用计数,使用得当一般不会出现内存问题
-
一般和
make_shared
结合使用,因为shared_ptr
本身会有两个变量,一个是存储原先对象,一个是存储引用计数,一般这两个内存地区会离得比较远,make_shared
会尽量让两个近一点,为后期的销毁节约时间。 -
shared_ptr
出现的循环引用的问题。
#include <algorithm>
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
struct ListNode
int value;
// std::weak_ptr<ListNode> next;
std::shared_ptr<ListNode> next;
~ListNode() std::cout << "~ListNode is called\\n";
;
int main(int argc, char const *argv[])
std::shared_ptr<ListNode> node1 = std::make_shared<ListNode>(); // node1.use_count() = 1
std::shared_ptr<ListNode> node2 = std::make_shared<ListNode>(); // node2.use_count() = 1
node1->next = node2; // node2.use_count() = 2
node2->next = node1; // node1.use_count() = 2
return 0;
上面的代码的输出结果为空,因为在销毁的时候,引用计数首先会 -1,然后看是否为 0 ,如果是,则会调用析构函数,没有则不会调用,这里我们很明显只会销毁一次,也就是在销毁对象的时候 ListNode
的析构函数不会被调用,因此会有内存泄漏的问题出现。但是这种写法其实对于一个链表来说又是经常会碰到的,怎么办呢?
- Solution
解决办法就是将 ListNode
里的 shared_ptr
换成 weak_ptr
,可以通过 shared_ptr
的类型对 weak_ptr
进行赋值,但此时并不会改变最初 shared_ptr
的引用计数。输出结果为:
~ListNode is called
~ListNode is called
weak_ptr.lock()
weak_ptr
指向shared_ptr
指针指向的对象的内存,却并不拥有该内存。 但是,使用weak_ptr
成员lock
,则可返回其指向内存的一个shared_ptr
对象,且在所指对象内存已经无效时,返回指针空值(nullptr
)。由于weak_ptr
是指向shared_ptr
所指向的内存的,所以,weak_ptr
并不能独立存在。
-
示例
C++
代码#include <algorithm> #include <iostream> #include <memory> #include <vector> using namespace std; struct ListNode int value; std::weak_ptr<ListNode> next; // std::shared_ptr<ListNode> next; ~ListNode() std::cout << "~ListNode is called\\n"; ; int main(int argc, char const *argv[]) std::shared_ptr<ListNode> node1 = std::make_shared<ListNode>(); // node1.use_count() = 1 std::shared_ptr<ListNode> node2 = std::make_shared<ListNode>(); // node2.use_count() = 1 node1->next = node2; // node2.use_count() = 2 node2->next = node1; // node1.use_count() = 2 std::cout << "///////////////////////////////////////\\n"; auto node3 = std::make_shared<ListNode>(); // node3.use_count() = 1 std::cout << "node3.use_count(): " << node3.use_count() << std::endl; auto node4 = std::make_shared<ListNode>(); // node4.use_count() = 1 std::cout << "node4.use_count(): " << node4.use_count() << std::endl; node4->next = node3; // 这两个都是对 weak_ptr 赋值,所以不会增加引用计数 std::cout << "node3.use_count(): " << node3.use_count() << std::endl; node3->next = node4; // 这两个都是对 weak_ptr 赋值,所以不会增加引用计数 std::cout << "node4.use_count(): " << node4.use_count() << std::endl; if (auto temp_ptr = node3->next.lock(); temp_ptr) std::cout << "Can access pointer\\n"; else std::cout << "Can not access pointer\\n"; return 0;
输出:
/////////////////////////////////////// node3.use_count(): 1 node4.use_count(): 1 node3.use_count(): 1 node4.use_count(): 1 ~ListNode is called Can not access pointer ~ListNode is called ~ListNode is called ~ListNode is called
以上是关于C++中的shared_ptr和weak_ptr的主要内容,如果未能解决你的问题,请参考以下文章
C++ shared_ptr&&weak_ptr的简单介绍和仿写
C++ 智能指针(shared_ptr/weak_ptr)源码分析