C++内存问题及智能指针

1.1 share_ptr

引用计数型智能指针
作用:解决内存泄露问题,管理共享资源
三种初始化方式:make_shared、new初始化(不能赋值)、另一个shared_ptr初始化。
使用shared_ptr注意事项:

  • 尽量不要使用相同的原始指针来创建多个shared_ptr对象,因为在这种情况下,不同的shared_ptr对象不会知道它们与其他shared_ptr对象共享指针。
int *rawPtr = new int();
std::shared_ptr<int> ptr_1(rawPtr);
std::shared_ptr<int> ptr_2(rawPtr);
  • 不要从栈而不是堆的内存中创建shared_ptr对象
#include <iostream>
#include <memory>
 
int main() {
  int x = 12;
  std::shared_ptr<int> ptr(&x);
  return 0;
}

1.2 shared_ptr模拟实现
template <T>
class SharedPtr {
public:
	SharedPtr(T* t):_ptr(t),_count(new int(1)) {}
	SharedPtr(const SharedPtr& sp):_ptr(sp._ptr),_count(sp._count){}

	SharedPtr<T>& operator=(const SharedPtr<T>& sp) {
		if(this != sp) {
			if(--(*_count) == 0) {
				delete _count;
				delete _ptr;
			}
			_ptr = sp._ptr;
			_count = sp._count;
			(*_count)++;
		}
		return *this;
	}

	~SharedPtr() {
		if(--(*_count) == 0){
			delete _count;
			delete _ptr;
		}
		else{
			(*_count)--;
		}
	}

	T& operator*() {
		return *_ptr;
	}

	T* operator->() {
		return _ptr;
	}

private:
	T* _ptr;
	int* _count;
}
1.3 shared_ptr循环引用

考虑双向链表的例子,pre和next指针都是shared_ptr
示例:

template<class T>
class SharedPtr;

template<class T>
struct ListNode
{
      T _data;
      SharedPtr<ListNode<T>> _next;
      SharedPtr<ListNode<T>> _prev;

      ListNode(T data)
           :_data(data)
           , _next(NULL)
           , _prev(NULL) {}
};
//中间部分与上面SharedPtr代码一样
void TestSharedPtr()
{
      SharedPtr<ListNode<int>> sp1(new ListNode<int> (10));
      SharedPtr<ListNode<int>> sp2(new ListNode<int>(20));
      sp1->_next = sp2;
      sp2->_prev = sp1;
}

分析:

  • 有两个share_ptr对象sp1和sp2,刚开始sp1和sp2的引用计数都为1;
  • 将sp2赋值给sp1->_next的时候,sp1->_next的引用计数变为2且sp2的引用计数也变为2;将sp1赋值给sp2->_prev时,sp2->_prev的引用计数变为2且sp1的引用计数也变为2。
  • 又因为sp1里的_next和_prev两个指针的释放依赖于sp1,而sp1的释放又依赖于sp2->_prev,sp2的_prev的释放又依赖于sp2,sp2又依赖于sp1的_next的释放,这就是我的释放依赖于你,你的释放依赖于我,就会导致陷入死循环中,导致空间没有被释放,进而就会产生内存泄露的问题。

更一般的情况是owner持有child的shared_ptr,而child又持有owner的shared_ptr,由此形成了循环引用,解决方法是让child持有owner的weak_ptr

2.weak_ptr

没有引用计数,一般用于解决循环引用问题。
weak_ptr本身也是一个模板类,但是不能直接用它来定义一个智能指针的对象,只能配合shared_ptr来使用,可以将shared_ptr的对象赋值给weak_ptr,并且这样并不会改变引用计数的值。
weak_ptr中只有函数lock和expired两个函数比较重要,因为它本身不会增加引用计数,所以它指向的对象可能在它用的时候已经被释放了,所以在用之前需要使用expired函数来检测是否过期,然后使用lock函数来获取其对应的shared_ptr对象。

3.unique_ptr

一个unique_ptr"拥有“他所指向的对象。与shared_ptr不同,某个时刻只能有一个unique_ptr指向一个给定的对象。当unique_ptr被销毁时,它所指向的对象也被销毁。uniptr_ptr表达的是一种独占的思想。

3. C++内存问题
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值