智能指针--标准库里的实现 scoped_ptr,share_ptr

在之前介绍了我们自己实现的ScopPtr和SharePtr,今天来看一下库里面的智能指针的实现

scoped_ptrshare_ptr包含于第三方boost库中,而且还被大家广泛使用。
所以在新的标准C++11中引用了boost库中智能指针的用法,只是将其稍作修改


将scoped_ptr重新定义为unique_ptr ,在boost库中不仅实现了share_ptr和scoped_ptr,还实现的share_array和scoped_array用来管理多个对象资源的保存和释放
这里我们先来模拟boost库中实现一个scoped_array,代码如下:

#include <iostream>
#include <stdio.h>
#include <windows.h>
#include <memory>

using namespace std;

template<class T>
class ScopedArray
{
public:
	ScopedArray(T* ptr) :_ptr(ptr)
	{}
	~ScopedArray()
	{
		delete[] _ptr;//释放时用delete[]
	}
	T & operator[](int pos)//重载了[]
	{
		return _ptr[pos];
	}
private:
	T * _ptr;
	ScopedArray(const ScopedArray<T> & p1);
	ScopedArray<T> &operator=(const ScopedArray<T> & p1);
};

void test()
{
	ScopedArray<int> p1(new int[10]);
	p1[0] = 1;
	p1[1] = 2;
	p1[2] = 3;
	
	cout << p1[0] << endl;
	cout << p1[1] << endl;
	cout << p1[2] << endl;
}

int main()
{
	test();
	system("pause");
	return 0;
}


现在来看C++11中的智能指针是用法:

#include <stdio.h>
#include <windows.h>
#include <memory>
#include <string>
#include <iostream>
using namespace std;

void test()
{
	auto_ptr<int> ap1(new int(10));
	cout << *ap1 << endl;
	unique_ptr<int> up1(new int(20));
	cout << *up1 << endl;
	shared_ptr<int> sp1(new int(30));
	cout << *sp1 << endl;

	/*auto_ptr<string> ap2(new string("hello world"));
	auto_ptr<string> ap3(ap2);
	cout << *ap3 << endl;//管理权转移的用法,下面的*ap2为解引用空指针
	cout << *ap2 << endl;*/

	//unique_ptr<string> up2(new string("somebody"));
	//unique_ptr<string> up3(up2);//编译不通过,下面是库里面的实现拷贝构造
	////unique_ptr(const _Myt&) = delete;
	////_Myt& operator=(const _Myt&) = delete;

}

int main()
{
	test();
	system("pause");
	return 0;
}

因为标准库里没有实现array版本,其实是有另外一种解决方法的。
先介绍一个新的概念:仿函数(函数对象)对象像函数一样使用
struct Less
{
	bool operator()(int a, int b)//重载了()
	{
		return a < b;
	}
};

void test_1()
{
	Less less;//感觉上像是实现了一个函数
	cout << less(1, 2) << endl;
}


因为智能智能管理的对象不一定是new出来的,有可能是new[],malloc ,fopen等等,所以要按其对用的方法正确是释放。例如:
//定制删除器
template<class T>
struct DeleteArray
{
	void operator()(T * ptr)
	{
		delete[] ptr;
	}
};

void test_2()
{
	DeleteArray<int> da;
	//ScopedArray<int> Sp1(new int[10]);
	
	int * p1 = new int[10];
	da(p1);//相当于delete[] p1;
}

C++11中的定制删除器就是用仿函数来实现的。

//实现一个普通的指针是释放。作为下面初始化时的缺省参数
template<class  T>
struct Delete
{
	void operator()(T * ptr)
	{
		delete ptr;
	}
};
//定制删除器
template<class T>
struct DeleteArray
{
	void operator()(T * ptr)
	{
		delete[] ptr;
	}
};

//针对于文件的定制删除器
struct FClose
{
	void operator()(FILE * fd)
	{
		fclose(fd);
	}
};
template<class T,class DA=Delete<int>>//缺省的处理方法为普通指针的释放
class ScopedPtr
{
public:
	ScopedPtr(T* ptr, DA da) :_ptr(ptr), _da(da)
	{}
	~ScopedPtr()
	{
		//delete _ptr;//释放时用delete
		_da(_ptr);//用定制删除器来实现释放
	}
	T& operator*()
	{
		return *_ptr;
	}
	T * operator->()
	{
		return _ptr;
	}
private:
	T * _ptr;
	DA _da;
	ScopedPtr(const ScopedPtr<T> & p1);
	ScopedPtr<T> &operator=(const ScopedPtr<T> & p1);
};



void test_2()
{
	DeleteArray<int> da;
	ScopedPtr<int, DeleteArray<int> > Sp1(new int[10], da);

	DeleteArray<string> da1;
	ScopedPtr<string, DeleteArray<string> > Sp2(new string[10], da1);

	ScopedPtr<FILE, FClose>Sp3(fopen("test.txt", "w"), FClose());
}

int main()
{
	test_2();

	system("pause");
	return 0;
}

如果是库里面的话,我们是不用传第二个模板参数的。
//定制删除器
template<class T>
struct DeleteArray
{
	void operator()(T * ptr)
	{
		delete[] ptr;
	}
};

//针对于文件的定制删除器
struct FClose
{
	void operator()(FILE * fd)
	{
		fclose(fd);
	}
};
template<class T, class DA = Delete<T>>//缺省的处理方法为普通指针的释放
class ScopedPtr
{
public:
	ScopedPtr(T* ptr, DA da) :_ptr(ptr), _da(da)
	{}
	~ScopedPtr()
	{
		//delete _ptr;//释放时用delete
		_da(_ptr);//用定制删除器来实现释放
	}
	T& operator*()
	{
		return *_ptr;
	}
	T * operator->()
	{
		return _ptr;
	}
private:
	T * _ptr;
	DA _da;
	ScopedPtr(const ScopedPtr<T> & p1);
	ScopedPtr<T> &operator=(const ScopedPtr<T> & p1);
};

void test_3()
{
	shared_ptr<string> sp1(new string[10], DeleteArray<string>());
	shared_ptr<string> sp2(new string, Delete<string>());
	shared_ptr<FILE> sp3(fopen("test.txt", "w"), FClose());
}
int main()
{
	test_3();
	system("pause");
	return 0;
}


猜你喜欢

转载自blog.csdn.net/misszhoudandan/article/details/80593251