C++11新特性 智能指针 unique_ptr shared_ptr weak_ptr 交叉引用

nuique_ptr

unique_ptr在要表达"专属所有权"的语义时使用,即unique_ptr指针永远′拥有"其指向的对象,所以unique_ptr是一个move-only类型,一个unique_ptr指针是无法被复制的,只能将"所有权"在两个unique_ptr指针之间转移,转移完成后原来的unique_ptr将被设为null;
智能指针是比原始指针更智能的类,解决悬空(dangling)指针或多次删除被指向对象,以及资源泄露问题,通常用来确保指针的寿命和其指向对象的寿命一致。智能指针虽然很智能,但容易被误用,智能也是有代价的。

特点

1 .基于排他所有权模式:两个指针不能指向同一个资源。这一块资源只能被一个指针指向
2.由于独占对象的拥有权,所以不提供拷贝构造函数和左值赋值函数重载。浅拷贝构造和浅赋值都是两个对象同时指向一个资源,
深拷贝,深赋值,同样的资源复制了一份,被两个unique对象指向,不行。
3.提供移动构造和移动赋值函数。
4 .为了实现单个对象和一组对象的管理,添加了删除器类型。
5.在容器保存指针是安全。
6.unique_ptr具有->和*运算符重载符,因此它可以像普通指针一样使用。


class PtrInt {
private:
	int* pval;
public:
	PtrInt(int x=0):pval(new int(x)){
		cout << "Create PtrInt" << this << endl;
	}
	~PtrInt() {
		delete pval;
		pval = nullptr;
		cout << "Destroy PtrInt" << this << endl;
	}
	PtrInt(const PtrInt& it) :pval(new int(10)) {
		if (it.pval != nullptr) {
			*pval = *it.pval;
		}
		cout  << this<< "Copy Create PtrInt" <<&it<< endl;
	}
	PtrInt& operator=(const PtrInt& it) {
		if (this != &it) {
			delete pval;
			if (it.pval != nullptr) {
				pval = new int(*it.pval);
			}
		}
		cout << this << "operator=()" << &it << endl;
		return *this;
	}
	PtrInt(PtrInt&& it) :pval(it.pval) {
		it.pval = nullptr;
		cout<<this << "Move Create PtrInt" << &it << endl;
	}
	PtrInt& operator=(PtrInt&& it) {
		if (this != &it) {
			delete[]pval;
			pval = it.pval;
			it.pval = nullptr;
		}
		cout << this << "Move operatro=()" << &it << endl;
		return *this;
	}
	void SetValue(int x) { *pval = x; }
	int GetValue()const { return *pval; }
	void Print()const {
		if (pval != nullptr) {
			cout << *pval << endl;
		}
	}

};


template<class _Ty>
class my_unique_ptr {
public:
	using pointer = _Ty*;
	using element_type = _Ty;
private:
	pointer mPtr;
public:
	my_unique_ptr(_Ty* p = nullptr) :mPtr(p){}
	//唯一性指针没有拷贝构造和左值赋值
	my_unique_ptr(const my_unique_ptr&) = delete;
	my_unique_ptr& operator=(const my_unique_ptr&) = delete;
	~my_unique_ptr() {
		if (mPtr != nullptr) {
			delete mPtr;
		}
		mPtr = nullptr;
	}
};

int main() {
	unique_ptr<PtrInt>pa(new PtrInt(10));
	pa->Print();
	return 0;
}

在这里插入图片描述
my_unique_ptrpa(new PtrInt(100));
在这里插入图片描述

不允许拷贝构造和赋值

唯一性智能指针不允许拷贝构造:浅拷贝pa pb的mPtr会指向同一个空间,析构时会把同一个地址释放两次,深拷贝就有了两份空间,应该只有一份

my_unique_ptr(const my_unique_ptr&) = delete;

也不允许赋值

my_unique_ptr& operator=(const my_unique_ptr&) = delete;

可以实现移动拷贝构造和移动赋值
移动之后,资源就不是以前的了,强行访问会崩溃

my_unique_ptr(my_unique_ptr&& x) :mPtr(x.mPtr) {
		x.mPtr = nullptr;
}
	//pa=move(pb);  //unique_
my_unique_ptr operator=(my_unique_ptr&& other) {
		if (this == &other)return *this;
		//my_unique_ptr(move(other)).swap(*this); 与下面三行等价
		delete mPtr;
		mPtr = other.mPtr;
		other.mPtr = nullptr;

		return *this;
}

运算符重载-> () *

在这里插入图片描述
pa是一个对象,访问对象的成员函数用.
为啥可以pa->
-> 都是用在结构体指针,->就是 先解引用,再 . 访问对象成员函数
这里重载了->
pa->Print();
pa.operator->()->Print();
等价

	pointer get()const { return mPtr; }
	_Ty& operator*()const { return *get(); }
	_Ty* operator->()const { return get(); }

在这里插入图片描述

int main() {
    unique_ptr<Int>pa(new Int(100));
    
	pa->Print();
	pa.operator->()->Print();
	
	return 0;
}
class Int {
	int value;
public:
	Int(int x = 0) :value(x) {
		cout << "Create Int " << endl;
	}
	~Int() { cout << "Destroy Int " << endl; }
	void SetValue(int x) { value = x; }
	int GetValue()const {
		return value;
	}
	void Print()const { cout << value << endl; }
};


template<class _Ty>
class my_unique_ptr {
public:
	using pointer = _Ty*;
	using element_type = _Ty;
private:
	pointer mPtr;
public:
	my_unique_ptr(_Ty* p = nullptr) :mPtr(p){}
	my_unique_ptr(const my_unique_ptr&) = delete;
	my_unique_ptr& operator=(const my_unique_ptr&) = delete;
	my_unique_ptr(my_unique_ptr&& x) :mPtr(x.mPtr) {
		x.mPtr = nullptr;
	}
	
	~my_unique_ptr() {
		if (mPtr != nullptr) {
			delete mPtr;
		}
		mPtr = nullptr;
	}
	pointer get()const { return mPtr; }
	_Ty& operator*()const { return *get(); }
	_Ty* operator->()const { return get(); }


};

int main() {
    unique_ptr<Int>pa(new Int(100));
	pa->Print();
	pa.operator->()->Print();

	return 0;
}

在这里插入图片描述
重载返回的mPtr ,*pa直接就是int对象,所以可以直接修改

int main() {
    unique_ptr<int>pa(new int(10));
	*pa = 100;
	pa.operator*() = 100;


	my_unique_ptr<Int>pb(new Int(10));
	//*pb返回的是一个Int对象 对象用. 访问成员函数Print()
	(*pb).Print();
	//上面已经解释过了,重载->
	pb->Print();

	return 0;
}

在这里插入图片描述

template<class _Ty>
class my_unique_ptr {
public:
	using pointer = _Ty*;
	using element_type = _Ty;
private:
	pointer mPtr;
public:
	my_unique_ptr(_Ty* p = nullptr) :mPtr(p){}
	my_unique_ptr(const my_unique_ptr&) = delete;
	my_unique_ptr& operator=(const my_unique_ptr&) = delete;
	my_unique_ptr(my_unique_ptr&& x) :mPtr(x.mPtr) {
		x.mPtr = nullptr;
	}
	//pa=move(pb);  //unique_
	my_unique_ptr operator=(my_unique_ptr&& other) {
		if (this == &other)return *this;
		//my_unique_ptr(move(other)).swap(*this); 与下面三行等价
		delete mPtr;
		mPtr = other.mPtr;
		other.mPtr = nullptr;

		return *this;
	}

	
	~my_unique_ptr() {
		if (mPtr != nullptr) {
			delete mPtr;
		}
		mPtr = nullptr;
	}
	pointer get()const { return mPtr; }
	_Ty& operator*()const { return *get(); }
	_Ty* operator->()const { return get(); }
	pointer release() {
		pointer old = mPtr;
		mPtr = nullptr;
		return old;
	}
	void reset(pointer ptr = nullptr) {
		if (mPtr != nullptr) {
			delete mPtr;
		}
		mPtr = ptr; 
	}
	void swap(my_unique_ptr& ptr) {
		swap(this->mPtr, it.mPtr);
	}
};

unique_ptr 删除器仿写

对申请的系统资源,重写一个删除器类型,专门针对系统资源释放,如果是new
则需要delete 如果是文件fopen,则需要用fclose

删除文件

template<class _Ty,class _Dx=my_default_deleter<_Ty>>
class my_unique_ptr {
public:
	using pointer = _Ty*;
	using element_type = _Ty;
	using deleter_type = _Dx;
private:
	pointer mPtr;
	deleter_type deleter;
public:
	deleter_type get_deleter()const { return deleter; }
	my_unique_ptr(_Ty* p = nullptr) :mPtr(p){}
	my_unique_ptr(const my_unique_ptr&) = delete;
	my_unique_ptr& operator=(const my_unique_ptr&) = delete;
	my_unique_ptr(my_unique_ptr&& x) :mPtr(x.mPtr) {
		x.mPtr = nullptr;
	}
	//pa=move(pb);  //unique_
	my_unique_ptr operator=(my_unique_ptr&& other) {
		if (this == &other)return *this;
		//my_unique_ptr(move(other)).swap(*this); 与下面三行等价
		delete mPtr;
		mPtr = other.mPtr;
		other.mPtr = nullptr;

		return *this;
	}

	
	~my_unique_ptr() {
		if (mPtr != nullptr) {
			get_deleter() (mPtr);
		}
		mPtr = nullptr;
	}
	pointer get()const { return mPtr; }
	_Ty& operator*()const { return *get(); }
	_Ty* operator->()const { return get(); }
	pointer release() {
		pointer old = mPtr;
		mPtr = nullptr;
		return old;
	}
	void reset(pointer ptr = nullptr) {
		if (mPtr != nullptr) {
			get_deleter()(mPtr);
		}
		mPtr = ptr; 
	}
	void swap(my_unique_ptr& ptr) {
		swap(this->mPtr,ptr.mPtr);
	}
};
struct FileDeleter {
	void operator()(FILE*ptr)const  {
		fclose(ptr);
	}
};
int main() {
my_unique_ptr<FILE>pa(fopen("xst.txt","w"));
	fprintf(pa.get(), "yhping\n");
	return 0;
}

删除普通对象

一组对象和单个对象的delete

template<class _Ty>
struct my_default_deleter {
	void operator()(_Ty* ptr)const {
		delete ptr;
	}
};
template<class _Ty>
struct my_default_deleter<_Ty[]> {
	void operator()(_Ty* ptr)const {
		delete[] ptr;
	}
};


template<class _Ty, class _Dx = my_default_deleter<_Ty>>
class my_unique_ptr{
public:
	using pointer = _Ty*;
	using element_type = _Ty;
	using deleter_type = _Dx;
private:
	pointer mPtr;
	deleter_type deleter;
public:
	deleter_type get_deleter()const { return deleter; }
	my_unique_ptr(_Ty* p = nullptr) :mPtr(p){}
	my_unique_ptr(const my_unique_ptr&) = delete;
	my_unique_ptr& operator=(const my_unique_ptr&) = delete;
	my_unique_ptr(my_unique_ptr&& x) :mPtr(x.mPtr) {
		x.mPtr = nullptr;
	}
	//pa=move(pb);  //unique_
	my_unique_ptr operator=(my_unique_ptr&& other) {
		if (this == &other)return *this;
		//my_unique_ptr(move(other)).swap(*this); 与下面三行等价
		delete mPtr;
		mPtr = other.mPtr;
		other.mPtr = nullptr;

		return *this;
	}

	
	~my_unique_ptr() {
		if (mPtr != nullptr) {
			get_deleter() (mPtr);
		}
		mPtr = nullptr;
	}
	pointer get()const { return mPtr; }
	_Ty& operator*()const { return *get(); }
	_Ty* operator->()const { return get(); }

	pointer release() {
		pointer old = mPtr;
		mPtr = nullptr;
		return old;
	}
	void reset(pointer ptr = nullptr) {
		if (mPtr != nullptr) {
			get_deleter()(mPtr);
		}
		mPtr = ptr; 
	}
	void swap(my_unique_ptr& ptr) {
		swap(this->mPtr,ptr.mPtr);
	}
};

class Int {
	int value;
public:
	Int(int x = 0) :value(x) {
		cout << "Create Int " << endl;
	}
	~Int() { cout << "Destroy Int " << endl; }
	void SetValue(int x) { value = x; }
	int GetValue()const {
		return value;
	}
	void Print()const { cout << value << endl; }
};


int main() {
	my_unique_ptr<Int[]>pa(new Int[10]{1,2,3,4,5,6,7,8,9,10});
	for (int i = 0; i < 10; i++) {
		pa[i].Print();
	}
	return 0;
}

在这里插入图片描述

make_unique

其实make_unique就是一个函数,封装了unique_ptr,他的返回值就是unique_ptr
make_unique 源码仿写

// FUNCTION TEMPLATE make_unique
//引用型别未定义 + 可变成模板 + 完美转发
template <class _Ty, class... _Types>
unique_ptr<_Ty> make_unique(_Types&&... _Args) { // make a unique_ptr
	return unique_ptr<_Ty>(new _Ty(forward<_Types>(_Args)...));
}

template <class _Ty[]>
unique_ptr<_Ty> make_unique(const size_t _Size) { // make a unique_ptr
	
	return unique_ptr<_Ty[]>(new  _Ty[_Size]());
}
int main() {
std::unique_ptr<Int> pa(new Int(10));
std::unique_ptr<Int> pb = std::make_unique<Int>(20);
std::unique_ptr<Int[]> pca(new Int[10]{ 1,2,3,4,5,6,7,8,9,10 }); 
std::unique_ptr<Int[]> pcb = std::make_unique<Int[]>(10);//不能初始化 默认都为0
return 0;
}

shared_ptr

shared_ptr实现了共享所有权(shared ownership)方式来管理资源对象,这意味没有一个特定的std::shared_ptr拥有资源对象。相反,这些指向同一个资源对象的stdushared_ptr相互协作来确保该资源对象在不需要的时候被析构。

特点

1 .基于共享所有权模式:多个指针能够同时指向同一个资源。
2.基于共享所有权,使用引用计数控制块管理资源对象的生命期。
3.提供拷贝构造函数和赋值重载函数;提供移动构造和移动赋值函数。
4 .为了实现单个对象和一组对象的管理,添加了删除器类型。
5.在容器保存shared_ptr对象是安全。
6 .shared_ptr重载了operator->和operator*运算符,因此它可以像普通指针一样使用。
两个共享指针指向同一个资源,该资源的引用计数加一

示意图

和唯一性指针的区别是加了一个引用计数块,一个资源一个引用计数块
在这里插入图片描述

int main() {
	shared_ptr<int>pa(new int(10));
	cout << pa.use_count() << endl;
	shared_ptr<int>pb(pa);
	cout << pb.use_count();
	return 0;
}

在这里插入图片描述

atomic<int>_Uses;

原子操作,使其过程不能被打断。

	~my_shared_ptr() {
		if (mRep != nullptr && mRep->Decref() == 0) {
			mDeleter(mPtr);
			delete mRep;
		}

资源需要用删除器删除,因为资源可能是API构建,释放也要API释放,而引用计数是new 所以释放 就是 delete
在这里插入图片描述

仿写shared_ptr

删除器部分特化

template<class _Ty>
struct My_Deleter
{
public:
	void operator()(_Ty* p) const
	{
		delete p;
	}
};
template<class _Ty>
struct My_Deleter<_Ty[]>
{
public:
	void operator()(_Ty* p) const
	{
		delete []p;
	}
};

拷贝构造 移动构造 && 左值赋值 和移动赋值

拷贝构造实现的时候,两个shared_ptr指向的是同一个资源,同一个引用技术块,引用的uses+1

My_shared_ptr(const My_shared_ptr& x)
		:mPtr(x.mPtr), mRep(x.mRep)
	{
		if (mRep != nullptr)
		{
			mRep->Incref();
		}
	}
	My_shared_ptr(My_shared_ptr&& other)
		:mPtr(other.mPtr),
		 mRep(other.mRep)
	{
		mPtr = nullptr;
		mRep = nullptr;
	}

分析一下这个程序:左值赋值
My_shared_ptr(x) 类型名加括号,构建不具名对象,调用拷贝构造,引用计数加1,是个将亡值,然后析构将亡值,引用计数减1,发现uses为0 ,就删除了 pa指向的资源和引用计数块,
如果pa指向的资源uses不是1,那么就不会删除该资源和引用计数块
在这里插入图片描述
移动赋值
如果原来的资源的引用计数为1,移动后需要释放,不为1 就减1
移动赋值后,指针pb就跟原来的资源么有多了关系,pb->printf 会崩,而左值赋值,有关系
std::move(other) 转成右值,

	My_shared_ptr& operator=(const My_shared_ptr& x)
	{
		if (this == &x) return *this;
		My_shared_ptr(x).swap(*this);
		return *this;
	}
	My_shared_ptr& operator=(My_shared_ptr&& other)
	{
		if (this == &other) return *this;
		My_shared_ptr(std::move(other)).swap(*this);
		return *this;
	}

完整实现

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <memory>
#include<atomic>
using namespace std;
class Int
{
private:
	int value;
public:
	Int(int x = 0) :value(x) { cout << "Create Int: " << endl; }
	Int(int x, int y) :value(x + y) { cout << "Create Int(int,int)" << endl; }
	~Int() { cout << "Destroy Int " <<value<<endl; }
	Int(const Int& it) :value(it.value)
	{
		cout << "copy Create Int: " << this << endl;
	}
	Int& operator=(const Int& it)
	{
		if (this != &it)
		{
			value = it.value;
		}
		cout << "operator=()" << endl;
		return *this;
	}
	void PrintInt() const
	{
		cout << value << endl;
	}
	int& Value() { return value; }
	const int& Value() const { return value; }

	operator int() const { return value; }
};


template<class _Ty>
struct My_Deleter
{
public:
	void operator()(_Ty* p) const
	{
		delete p;
	}
};
template<class _Ty>
struct My_Deleter<_Ty[]>
{
public:
	void operator()(_Ty* p) const
	{
		delete []p;
	}
};


template<class _Ty>
class My_RefCount
{
public:
	using element_type = _Ty;
	using pointer = _Ty*;
private:
	_Ty* _Ptr;
	std::atomic<int> _Uses; // shared;
	std::atomic<int> _Weaks; // weak_ptr;
public:
	My_RefCount(_Ty* ptr = nullptr) :_Ptr(ptr), _Uses(0), _Weaks(0)
	{
		if (_Ptr != nullptr)
		{
			_Uses = 1;
			_Weaks = 1;
		}
	}
	~My_RefCount() = default;
	void Incref() { ++_Uses; }
	void Incwref() { ++_Weaks; }
	int Decref()
	{
		if (--_Uses == 0)
		{
			Decwref();
		}
		return _Uses;
	}
	int Decwref()
	{
		return --_Weaks;
	}
	int _use_count() const
	{
		return _Uses.load();
	}
};



template<class _Ty,class _Dx = My_Deleter<_Ty>>
class My_shared_ptr
{
public:
	using MyDeleter = _Dx;
private:
	_Ty*               mPtr;
	My_RefCount<_Ty> * mRep;
	MyDeleter          mDeleter;
public:
	My_shared_ptr(_Ty* ptr = nullptr) :mPtr(ptr), mRep(nullptr)
	{
		if (mPtr != nullptr)
		{
			mRep = new My_RefCount<_Ty>(mPtr);
		}
	}
	My_shared_ptr(const My_shared_ptr& x)
		:mPtr(x.mPtr), mRep(x.mRep)
	{
		if (mRep != nullptr)
		{
			mRep->Incref();
		}
	}
	My_shared_ptr(My_shared_ptr&& other)
		:mPtr(other.mPtr),
		 mRep(other.mRep)
	{
		mPtr = nullptr;
		mRep = nullptr;
	}
	My_shared_ptr& operator=(const My_shared_ptr& x)
	{
		if (this == &x) return *this;
		My_shared_ptr(x).swap(*this);
		return *this;
	}
	My_shared_ptr& operator=(My_shared_ptr&& other)
	{
		if (this == &other) return *this;
		My_shared_ptr(std::move(other)).swap(*this);
		return *this;
	}

	~My_shared_ptr()
	{
		if (nullptr != mRep && 0 == mRep->Decref())
		{
			mDeleter(mPtr);
			delete mRep;
		}
		mPtr = nullptr;
		mRep = nullptr;
	}

	int use_count() const
	{
		return mRep != nullptr ? mRep->_use_count() : 0;
	}

	_Ty * get() const { return mPtr; }
	_Ty& operator*() const { return *get(); }
	_Ty* operator->() const {return get();}
	operator bool() const { return mPtr != nullptr; }
	void swap(My_shared_ptr& other)
	{
		std::swap(this->mPtr, other.mPtr);
		std::swap(this->mRep, other.mRep);
	}
	void reset()
	{
		if (mRep != nullptr && 0 == mRep->Decref())
		{
			mDeleter(mPtr);
			delete mRep;
		}
		mRep = nullptr;
		mPtr = nullptr;
	}
	void reset(_Ty* p)
	{
		if (nullptr == p)
		{
			reset();
			return;
		}
		if (mRep != nullptr && 0 == mRep->Decref())
		{
			mDeleter(mPtr);
			delete mRep;
			mRep = nullptr;
		}
		mPtr = p;
		if (mPtr != nullptr)
		{
			mRep = new My_RefCount(mPtr);
		}
	}
};

weak_ptr

特点

弱引用指针weak_ptr是用来监视shared_ptr的生命周期,是shared_ptr的一个助手。weak_ptr没有重载操作符*和->,因为它不与shared_ptr共享指针,不能操作资源,主要是通过shared_ptr获得资源的监测权,它的构造不会增加引用计数,它的析构也不会减少引用计数,纯粹只是作为一个旁观者来监视shared_ptr中管理的资源是否存在。weak_ptr还可以用来返回this 指针和解决循环引用的问题。

当我们创建一个weak_ptr时,需要用一个shared_ptr实例来初始化weak_ptr,由于是弱共享,weak_ptr的创建并不会影响shared_ptr的引用计数值。可以通过use_count()方法来获得当前观测资源的引用计数。

weak_ptr 实现

注意带参数的构造函数是对weaks加1 不是uses加1 对弱引用计数值增加和减少

template<class _Ty>
class My_weak_ptr
{
private:
	My_RefCount<_Ty>* mRep;
public:
	My_weak_ptr() :mRep(nullptr) {}
	My_weak_ptr(const My_shared_ptr<_Ty>& other)
	{
		mRep = other.mRep;
		if (mRep != nullptr)
		{
			mRep->Incwref();
		}
	}
	~My_weak_ptr()
	{
		if (mRep != nullptr)
		{
			mRep->Decwref();
		}
	}
};

解决循环引用

class Parent;
class Child
{
public:
	//std::shared_ptr<Parent> parent;
	std::weak_ptr<Parent> parent;
	Child() { cout << "Create Child" << endl; }
	~Child() { cout << "~Child" << endl; }
};
class Parent
{
public:
	//std::shared_ptr<Child> child;
	std::weak_ptr<Child> child;
	Parent() { cout << "Create Parent" << endl; }
	~Parent() { cout << "~Parent" << endl; }
	void Hi() { cout << "hello yhping" << endl; }
};
int main()
{
	std::shared_ptr<Parent> pa(new Parent());
	std::shared_ptr<Child>  cp(new Child());
	pa->child = cp;
	cp->parent = pa;
	return 0;
}


在这里插入图片描述
无法释放对象,pa和cp析构后,计数块都变成了 1 1,因为uses减为了1,只是把pa.mPtr和pa.mRep置为了空,调用析构函数时,无法删除资源和计数块

用弱指针就能解决该问题

弱引用指针只能对weaks加1,共享性指针只能对uses加一
只有当uses和weaks同时为0,才能删除该资源
uses为0可以析构资源,但是不能析构计数块,weaks为0 uses为0 才能析构计数块
如图:
在这里插入图片描述

过程就是:假如先析构cp ,uses减1为0 weaks减1 此时左下计数块为 0 1 所以 释放child对象 ,该对象有mRep 所以 左下计数块里面的weaks减1,此时左下计数块 为 1 1再析构pa对象,此时析构pa,左下计数块 中uses减1,为0,此时weaks再减一为0,可以将该计数块析构,所以将左上对象释放,有弱引用指针,此时将右下计数块,weaks为0,析构计数块,析构右上 child对象在这里插入图片描述

弱指针一个应用

应用就是
删除父节点,子节点也会被自动释放删除,析构子节点,父节点不会被析构

template<class KeyType>
class BSTree
{
public:
	struct BstNode
	{
		std::shared_ptr<BstNode> leftchild;
		std::weak_ptr<BstNode> parent;
		std::shared_ptr<BstNode> rightchild;
		KeyType key;
	public:
		BstNode(const KeyType& kx)
			:key(kx)
		{
		}
		~BstNode()
		{

		}
	};
private:
	 std::shared_ptr<BstNode> root;

	static void InOrder(std::shared_ptr<BstNode> ptr)
	{
		if (ptr)
		{
			InOrder(ptr->leftchild);
			cout << ptr->key << " ";
			InOrder(ptr->rightchild);
		}
	}
public:
	BSTree() :root(nullptr) {}
	~BSTree()
	{

	}
	bool Insert(const KeyType& kx)
	{
		if (!root)  // root.operator bool()
		{
			root = std::make_shared<BstNode>(kx);  // Root;
			return true;
		}
		std::shared_ptr<BstNode> pa(nullptr);
		std::shared_ptr<BstNode> p = root;
		while (p && p->key != kx)
		{
			pa = p;
			p = kx > p->key ? p->rightchild : p->leftchild;
		}
		if (p && p->key == kx)
		{
			cout << "key 重复 " << endl;
			return false;
		}

		p = std::make_shared<BstNode>(kx);
		p->parent = pa;
		if (p->key > pa->key)
		{
			pa->rightchild = p;
		}
		else
		{
			pa->leftchild = p;
		}

		return true;
	}

	void InOrder() const
	{
		InOrder(root);
		cout << endl;
	}
};
int main()
{
	int ar[] = { 53,17,78,9,45,65,87,23,81,94,88 };
	BSTree<Int> mytree;
	Int tmp;
	for (auto& x : ar)
	{
		tmp.Value() = x;
		mytree.Insert(tmp);
	}
	mytree.InOrder();
	return 0;
}
shared_ptr<Int>pa(new Int(10));
shared_ptr<Int>pb=make_shared<Int>(20);

区别是pa 用了两次new 第二次开辟计数块的空间,而pb开辟一次,

weaks就是只要是指针指向,就算一个,弱指针和共享指针都可以,而uses必须是shared指针,才算数
pb空间只有等weaks为0才能释放,mPtr指向的和mPep指向的绑在一起了

My_shared_ptr(_Ty* ptr = nullptr) :mPtr(ptr), mRep(nullptr)
{
	if (mPtr != nullptr)
	{
		mRep = new My_RefCount<_Ty>(mPtr);
	}
}

创建共享性指针的时候,有两个参数 ,指定所需的删除器,唯一性指针不具有,弱指针不具备删除对象

shared_ptr<Int>pa(new Int(10),DeleteInt);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值