C++:智能指针( scope_ptr)

新智能指针的加入:

C++11之前,智能指针只有 auto_ptr 一种,但是后来发现它并不能很好的保证指针的安全可靠性,随之又出现了

shared_ptr     unique_ptr     weak_ptr   scope_ptr 这几种智能指针。

假如存在这样的代码
int main()
{
    SmartPtr<int> sp1(new int);
    SmartPtr<int> sp2(sp1);

    *sp1 = 20;
     return 0;
}

这里,SmartPtr即为之前博客实现的auto_ptr,显而易见,*sp1=20;这行会出现崩溃。

               

解决方案:

 之前的auto_ptr,管理权唯一,释放权也唯一,现在要使智能指针管理权不唯一,释放权唯一。

带有标志位(flag)的智能指针

如图:

                 

             

代码:

#include<iostream>

using namespace std;

template<typename T>
class SmartPtr
{
public:
	SmartPtr(T* ptr) :mptr(ptr)
	{
		flag = true;
	}
	SmartPtr(const SmartPtr<T>& rhs):mptr(rhs.mptr)
	{
		flag = rhs.flag;
		rhs.flag = false;
	}
	SmartPtr<T>& operator=(const SmartPtr<T>& rhs)
	{
		if (this != &rhs)
		{
			~SmartPtr();
			mptr = rhs.mptr;
			flag = rhs.flag;
			rhs.flag = false;
		}
		return *this;
	}
	~SmartPtr()
	{
		if (flag)
		{
			delete mptr;
		}
		mptr = NULL;
	}
	T& operator*()
	{
		return *mptr;
	}
	T* operator->()
	{
		return mptr;
	}
private:
	T* mptr;
	mutable bool flag;//去除常性
};

int main()
{
	SmartPtr<int> sp1(new int);
	SmartPtr<int> sp2(sp1);
        SmartPtr<int> sp3(sp1);

	*sp1 = 20;

	return 0;
}

这里程序不会崩溃,有释放权的只有sp2。

又一个问题

因为释放权的转移,有可能导致堆内存被提前释放

void func(SmartPtr<int> sp)//实参传形参 调用拷贝构造
{

}

int main()
{
	SmartPtr<int> sp1(new int);
	SmartPtr<int> sp2(sp1);
	SmartPtr<int> sp3(sp1);

	func(sp2);//;执行结束后,形参对象销毁  相当于堆内存已经归还给系统
	*sp1 = 20;//使用不可使用的内存块 野指针 该内存块可能被再分配
	return 0;
}

调用这个函数,实参传形参 调用拷贝构造,func(sp2);//;执行结束后,形参对象销毁  相当于堆内存已经归还给系统。

*sp1 = 20;//使用不可使用的内存块 野指针 该内存块可能被再分配,会出现不可预期的数据错误。

解决: ScopePtr  不允许多个智能指针对象指向同一块堆内存

#include<iostream>

using namespace std;

template<typename T>
class ScopePtr//不允许多个智能指针对象指向同一块堆内存
{
public:
	ScopePtr(T* ptr=NULL):mptr(ptr)
	{
		//mptr = ptr;
	}
	~ScopePtr()
    {
		delete mptr;
		mptr = NULL;
	}
	T& operator*()
	{
		return *mptr;
	}
	T* operator->()
	{
		return mptr;
	}
private:
	ScopePtr(const ScopePtr<T>& rhs);//不需要调用,因为不允许多个智能指针对象指向同一块堆内存
	ScopePtr<T>& operator=(const ScopePtr<T>& rhs);//不允许多个智能指针对象指向同一块堆内存
private:
	T* mptr;
};

int main()
{
	int* p = new int;
	ScopePtr<int> sp1(p);
	ScopePtr<int> sp2(p);
	ScopePtr<int> sp3(p);//后构造的先析构
	return 0;
}

    int* p = new int;
    ScopePtr<int> sp1(p);
    ScopePtr<int> sp2(p);
    ScopePtr<int> sp3(p);//后构造的先析构
    

这个程序会崩溃,后构造的先析构,然后先构造的再析构时,delete野指针,程序崩溃。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值