极简版shared_ptr实现

程序如下:

头文件:

#ifndef PCH_H
#define PCH_H
#include
#include
using namespace std;
class like_shared_ptr {
public:
	//交换函数
	friend void swap(like_shared_ptr&, like_shared_ptr&);
	//比较like_shared_ptr大小函数
	friend bool comparesize(const like_shared_ptr&,const like_shared_ptr&);
	//默认构造函数
	like_shared_ptr():number(new int(0)),location(NULL){}
    //接受指针的构造函数
	like_shared_ptr(string* a) :location(a), number(new int(1)) {}
	//拷贝构造函数
	like_shared_ptr(const like_shared_ptr&);
	//析构函数
	~like_shared_ptr(); 
	//赋值运算符
	like_shared_ptr& operator =(like_shared_ptr);
	//*运算符 
	string& operator *()const;
	//->运算符
	string* operator->()const;
private:
	//计数器
	int* number;
	//内容的指针
	string* location;
	//此函数用于定义交换操作,替代标准库的swap函数
};
void swap(like_shared_ptr&, like_shared_ptr&);
bool comparesize(const like_shared_ptr&, const like_shared_ptr&);
#endif //PCH_H
/*头文件里面除非是非常简单的程序,否则不要定义函数,太乱的话,不利于自己维护和观看*/

.cpp文件:

#include "pch.h"
//拷贝赋值
like_shared_ptr& like_shared_ptr::operator =(like_shared_ptr a) {
	//shared_ptr为空和唯一
	if (*number == 1 || *number == 0)
	{
		delete number;
		delete location;
	}
	//存在多个
	else {
		--*number;
	}
	/*location = a.location;
	number = a.number;*/
	swap(*this, a);
	//为空的情况不需要number++
	if (location != NULL)
		++*number;
	return *this;
}
//拷贝构造
like_shared_ptr::like_shared_ptr(const like_shared_ptr& a)
{
	location = a.location;
	number = a.number;
	//空shared_ptr并不需加number   当然实际上加不加都不会出现问题 
	if (location != NULL)
		++*number;
}
//析构
like_shared_ptr::~like_shared_ptr() {
		//这里如果number为NULL的话,执行到这里会发生运行时错误,但是编译时报不出错误,这种错误比较严重并且难以查找
		//添加上number==null就可以了,对空的指针delete没有任何动作
		if (*number == 1||*number==0) {
			delete number;
			delete location;
		}
		else {
			--*number;
		}
}
//*运算符重载(可以时一元运算符也可以是二元运算符,根据重载函数中的参数来)
string& like_shared_ptr::operator *()const {
	return *location;
}
//->运算符重载(一元运算符,只接受一个餐宿)
string* like_shared_ptr::operator ->()const {
	return location;
}
/*这里参数要是引用,不然会出现没有交换而访问释放了的地址的错误,访问控制错误
实际上根据本例的的要求并不需要定义这个swap函数,仅仅是想要实验一番*/
void swap(like_shared_ptr& a,like_shared_ptr& b) {
	cout << "swap" << endl;
	using std::swap;
	swap(b.location, a.location);
	swap(b.number, a.number);
}
//比较like_shared_ptr大小函数
bool comparesize( const like_shared_ptr& a, const like_shared_ptr& b) {
	cout << "comparesize" << endl;
	if (*b.location > *a.location)
		return true;
	else
		return false;
}

main函数:

#include "pch.h"
#include 
#include
#include
#include
using namespace std;
int main()
{
		like_shared_ptr a;
		like_shared_ptr b(new string("xiaoming"));
		cout << *b << endl;
		cout <<(*b).size()<< endl;
		//这里调用string对象中的size()函数
		cout <size() << endl;
		//这里调用了一次swap
		a = b;
		*a = "xiaowang";
		cout << *a << endl;
		like_shared_ptr c(b);
		cout << *c << endl;
		like_shared_ptr d;
		//这里调用了一次swap
		d = a;
		cout << endl << endl << endl;
		vector e;
		e.push_back(a);
		e.push_back(b);
		e.push_back(c);
		e.push_back(d);
		//这里我们需要传递第三个参数,不然sort函数没有办法比较比较like_shared_ptr对象
		//sort中调用了swap函数,因为我们定义了自己的版本,所以呢,调用自己定义的版本
		sort(e.begin(), e.end(),comparesize);
		//这里遍历的时候里面不能有空的like_shared_ptr,不然会发生读取错误,location为nullptr,并不能读其中内容。
		for (auto a : e) {
			cout << *a << endl;
		}

}
/*总结:
  1.运算符*和—>运算符重载:
    如果返回的时对象指针的话,不需要再->来使用成员变量和成员函数,直接即可。而对于返回的时对象,则需要加.来使用
    或许可以从这里看到点什么东西。
    当我们用指针访问对象时,可以直接访问私有成员。
    而用对象的话,并不能直接访问私有成员。或许这两者之间底层的实现方式不同哦。
    这里->运算符之后好像只能接成员变量和成员函数,其他的都会报错
  2.全局函数的问题,
  全局变量要再头文件中进行声明,不管是不是友元函数,都是这样。
*/

额,对于这个程序没有什么要说的,主要是了解shared_ptr如何可以多个指向同一段堆空间的实现方式。

之前考虑也可以通过类的静态成员变量来实现,但是标准库采用了这种方式来实现。利弊大家可以思考思考哦。

你可能感兴趣的:(C++)