C++:智能指针( scope_ptr)

本文探讨了C++中智能指针的概念及其改进过程。从auto_ptr的局限性出发,介绍了通过引入标志位解决管理权和释放权的问题,并进一步讨论了ScopePtr如何避免多个智能指针指向同一堆内存的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

新智能指针的加入:

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野指针,程序崩溃。

#include "../utils.h" #include "StringLengthVariance.h" #include <algorithm> #include <vector> std::vector<std::shared_ptr<StringBase>> StringLengthVariance::mutated_elements; StringLengthVariance::StringLengthVariance(std::shared_ptr<StringBase> obj, std::mt19937 &rand) : IntegerVariance(std::static_pointer_cast<StringBase>(obj), rand, false) {} std::pair<int64_t, int64_t> StringLengthVariance::get_limits(std::shared_ptr<StringBase> obj) { /* TODO:获取长度边界代码待完善 */ int64_t max_output_size_bits = static_cast<int64_t>(obj->mutator_config.max_output_size * 8); int64_t size_bits = llrint(obj->calculate_bit_size()); int64_t limit_bits = std::max(max_output_size_bits, size_bits); int64_t limit_bytes = (limit_bits + 7) / 8; int64_t max_length = limit_bytes; if (obj->max_length != nullptr) { max_length = std::min(limit_bytes, static_cast<int64_t>(obj->max_length.value())); } int64_t min_length = 0; if (obj->min_length.has_value()) { min_length = std::max(0LL, static_cast<int64_t>(obj->min_length.value())); } return {min_length, max_length}; } int64_t StringLengthVariance::get_value(std::shared_ptr<StringBase> obj) { return std::min(static_cast<int64_t>(obj->value.size()), max_); } void StringLengthVariance::perform_mutation(std::shared_ptr<StringBase> obj, int64_t value) { obj->mutated_value = expand(obj->value, static_cast<size_t>(value)); obj->mutated = true; mutated_elements.push_back(obj); } bool StringLengthVariance::supported(std::shared_ptr<StringBase> obj) { return std::dynamic_pointer_cast<StringBase>(obj) != nullptr; } std::vector<std::shared_ptr<StringBase>> StringLengthVariance::get_mutated_elements() { return mutated_elements; }报错/data/k50048780/cpp_mutator/mutators/string/StringLengthVariance.cpp: In member function ‘virtual std::pair<long int, long int> StringLengthVariance::get_limits(std::shared_ptr<StringBase>): /data/k50048780/cpp_mutator/mutators/string/StringLengthVariance.cpp:24:25: error: request for member ‘has_value’ in ‘((std::__shared_ptr_access<StringBase, __gnu_cxx::_S_atomic, false, false>*)(& obj))->std::__shared_ptr_access<StringBase, __gnu_cxx::_S_atomic, false, false>::operator->()->StringBase::<anonymous>.TypeBase<StringBase>::max_length’, which is of non-class type ‘int64_t’ {aka ‘long int’} 24 | if (obj->max_length.has_value()) { | ^~~~~~~~~ /data/k50048780/cpp_mutator/mutators/string/StringLengthVariance.cpp:25:81: error: request for member ‘value’ in ‘((std::__shared_ptr_access<StringBase, __gnu_cxx::_S_atomic, false, false>*)(& obj))->std::__shared_ptr_access<StringBase, __gnu_cxx::_S_atomic, false, false>::operator->()->StringBase::<anonymous>.TypeBase<StringBase>::max_length’, which is of non-class type ‘int64_t’ {aka ‘long int’} 25 | max_length = std::min(limit_bytes, static_cast<int64_t>(obj->max_length.value())); | ^~~~~ /data/k50048780/cpp_mutator/mutators/string/StringLengthVariance.cpp:28:25: error: request for member ‘has_value’ in ‘((std::__shared_ptr_access<StringBase, __gnu_cxx::_S_atomic, false, false>*)(& obj))->std::__shared_ptr_access<StringBase, __gnu_cxx::_S_atomic, false, false>::operator->()->StringBase::<anonymous>.TypeBase<StringBase>::min_length’, which is of non-class type ‘int64_t’ {aka ‘long int’} 28 | if (obj->min_length.has_value()) { | ^~~~~~~~~ /data/k50048780/cpp_mutator/mutators/string/StringLengthVariance.cpp:29:73: error: request for member ‘value’ in ‘((std::__shared_ptr_access<StringBase, __gnu_cxx::_S_atomic, false, false>*)(& obj))->std::__shared_ptr_access<StringBase, __gnu_cxx::_S_atomic, false, false>::operator->()->StringBase::<anonymous>.TypeBase<StringBase>::min_length’, which is of non-class type ‘int64_t’ {aka ‘long int’} 29 | min_length = std::max(0LL, static_cast<int64_t>(obj->min_length.value())); | ^~~~~ /data/k50048780/cpp_mutator/mutators/string/StringLengthVariance.cpp: At global scope: /data/k50048780/cpp_mutator/mutators/string/StringLengthVariance.cpp:48:42: error: no declaration matches ‘std::vector<std::shared_ptr<StringBase> > StringLengthVariance::get_mutated_elements()’ 48 | std::vector<std::shared_ptr<StringBase>> StringLengthVariance::get_mutated_elements() { | ^~~~~~~~~~~~~~~~~~~~ /data/k50048780/cpp_mutator/mutators/string/StringLengthVariance.cpp:48:42: note: no functions named ‘std::vector<std::shared_ptr<StringBase> > StringLengthVariance::get_mutated_elements()’ In file included from /data/k50048780/cpp_mutator/mutators/string/StringLengthVariance.cpp:6: /data/k50048780/cpp_mutator/mutators/string/StringLengthVariance.h:13:7: note: ‘class StringLengthVariance’ defined here 13 | class StringLengthVariance : public IntegerVariance { | ^~~~~~~~~~~~~~~~~~~~
07-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值