c++智能指针

       c++的类相较于c的结构体来说,在创建与销毁时会调用构造函数与析构函数,因此有人提出来了一种天才般的想法来解决c++的内存泄露问题,即在析构函数中进行内存释放-----智能指针即使基于这一想法实现的

#include <iostream>
using namespace std;
template<class T>
class smart_ptr {
public:
	smart_ptr(T* ptr)
		:_ptr(ptr)
	{}
	~smart_ptr()
	{
		cout << "delete[]_ptr" << endl;
		// 将delete放进析构函数 ,类的声明周期结束自动进行回收
		delete[]_ptr;
	}
	T* Get() {
		return _ptr;
	}
private:
	T* _ptr;
};
int main()
{
	smart_ptr<int> sp = new int[100];
	system("pause");
	return 0;
}

系统提供的智能指针在头文件<memory>下

c++库里的几种智能指针

基于不同使用的环境,在构造与赋值处有不同的实现方式

  • auto_ptr                          用auto_ptr向auto_ptr赋值时,会使发生管理权转移,赋值方将变为空 (个人感觉设计的不太好,慎用!)
  • unique_ptr                     简单粗暴,禁止拷贝,禁止复制
  • shared_ptr                     允许拷贝赋值,内部使用引用计数,最常用,循环引用时会出问题
  • weak_ptr                        用来解决shared_ptr循环引用的问题,可有shared_ptr赋值,不会使引用计数增加

循环引用

现有一个双向链表如下图所示,已知智能指针node1与node2->next指向同一块内存,引用计数为2。智能指针node2与node1->prev指向同一块内存,引用计数为2,如果我要释放node1指向的空间,需要先让这块空间的引用计数为0,所以我需要在释放node1指向的空间之前先析构node2->next,也就是释放node2指向的空间,而同理,如果我要释放node2指向的空间,也要先释放node1,死循环,出现异常

解决方案为prev和next使用weak_ptr,因为这个智能指针不会增加引用计数

// 错误例子
class node {

public:
	shared_ptr<node> prev;
	shared_ptr<node> next;
	int val;
	~node() {
		cout << "delect " << endl;
	}
};

int main()
{
	shared_ptr<node> n1(new node);
	shared_ptr<node> n2(new node);
	n1->next = n2;
	n2->prev = n1;
	return 0;
}

定制删除器

对于一个智能指针来说,他可能用来维护

  1. malloc
  2. new
  3. FILE*
  4. 线程锁
  5. ...

维护的对象不同显然析构时调用的对象也应该不同,最好的办法就是删除器有使用者自己提供

shared_ptr模拟实现

#pragma once
#include <iostream>
#include <atomic>
#include <functional>
namespace mystd {
	template<class T>
	class shared_ptr {
	public:
		shared_ptr(T* ptr) 
			:_ptr(ptr),_pcount(new std::atomic<int>(1))
		{}
		template<class D>
		shared_ptr(T* ptr, D del)
			: _ptr(ptr), _pcount(new std::atomic<int>(1)), _del(del)
		{}
		shared_ptr(const shared_ptr<T>& sp)
			:_ptr(sp._ptr), _pcount(sp._pcount)
		{
			++(*_pcount);
		}
		void release() {
			if (--(*_pcount));
			else {
				_del(_ptr);
				delete _pcount;
			}
		}
		~shared_ptr()
		{
			release();
		}
		int use_count() {
			return *_pcount;
		}
		shared_ptr<T>& operator=(const shared_ptr<T>& sp) {
			shared_ptr<T> tmp(sp);
			swap(tmp);
			return *this;
		}
		void swap(shared_ptr<T>& sp) {
			std::swap(_ptr, sp._ptr);
			std::swap(_pcount, sp._pcount);
		}
		T& operator*() {
			return *_ptr;
		}
		T* operator->() {
			return _ptr;
		}
	private:
		T* _ptr;
		std::atomic<int>* _pcount;
		std::function<void(T*)> _del = [](void* ptr) {delete ptr; };
	};
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值