0
点赞
收藏
分享

微信扫一扫

【大数据】gRPC、Flink、Kafka 分别是什么?

萨科潘 2024-06-22 阅读 31

 问题引入

int func1(int x)
{
	int y = 10;
	int* tmp = (int*)malloc(sizeof(int) * 2);
	if (x == 0)
		throw "func1_error";
	else
		return x + y;
	free(tmp);//抛异常造成异常安全问题,无法释放造成内存泄漏,
}

int main()
{
	try { int a=func1(0); }
	catch (const char* error)
	{
		cout << error << endl;
	}
	return 0;
}

智能指针的使用及原理

RAII(面试官喜欢问)

使用RAII思想设计的Smart_sptr类


template<class T>
class Smart_sptr
{
public:
	Smart_sptr(T* sptr=nullptr)
		:_ptr(sptr) 
	{}

	~Smart_sptr()
	{ 
		if (_ptr)
		{
			delete _ptr;
			cout << "~Smart_sptr" << endl;
		}
			
	}

	T& operator*() { return *_ptr; }
	T* operator->() { return _ptr; }

private:
	T* _ptr;
};

struct Date
{
	int _year;
	int _month;
	int _day;
};


int main()
{
	//实现指针操作
	Smart_sptr<int> sp1(new int);
	*sp1 = 10;
	cout << *sp1 << endl;


	//管理资源
	Smart_sptr<Date> sp2(new Date);
	// 需要注意的是这里应该是sparray.operator->()->_year = 2018;
	// 本来应该是sparray->->_year这里语法上为了可读性,省略了一个->
	sp2->_year = 2018;
	sp2->_month = 1;
	sp2->_day = 1;
	cout << sp2->_year << " " << sp2->_month << " " << sp2->_day << endl;
	
	//测试生命周期
	cout << (*(Smart_sptr<int>(new int)) = 11) << endl;
	//执行完后立马析构,资源释放
	return 0;
}

 std::auto_ptr

C++98版本的库中就提供了auto_ptr的智能指针。

#include <memory>
class Date
{
public:
	Date() { cout << "Date()" << endl; }
	~Date() { cout << "~Date()" << endl; }
	int _year;
	int _month;
	int _day;
};
int main()
{
	auto_ptr<Date> ap(new Date);
	auto_ptr<Date> copy(ap);
	// auto_ptr的问题:当对象拷贝或者赋值后,前面的对象就悬空了copy()括号内的内容悬空
	// C++98中设计的auto_ptr问题是非常明显的,所以实际中很多公司明确规定了不能使用auto_ptr
	ap->_year = 2018;
	return 0;
}

std::unique_ptr

int main()
{
	unique_ptr<Date> up(new Date);

	// unique_ptr的设计思路非常的粗暴-防拷贝,也就是不让拷贝和赋值。
	unique_ptr<Date> copy(ap);
	return 0;
}

std::shared_ptr

 简单样例

struct Date
{
	int _year;
	int _month;
	int _day;
};

int main()
{
	// shared_ptr通过引用计数支持智能指针对象的拷贝
	shared_ptr<Date> sp(new Date);
	//use_count()返回引用计数个数
	cout << "第一个对象sp管理new Date的引用计数:" << sp.use_count() << endl;

	shared_ptr<Date> copy(sp);
	cout << "新增一个对象后sp的引用计数:" << sp.use_count() << endl;
	cout << "第二个对象copy管理new Date的引用计数:" << copy.use_count() << endl;
	return 0;
}

图解

shared_ptr的原理:

模拟实现Shared_Ptr

初级版本

#include<string>
template<class T>
class Shared_Ptr
{
public:
	//构造
	Shared_Ptr(T* ptr = nullptr)
		:_ptr(ptr)
		, _pcount(new int(1))//数组,开始初始化赋值为1
	{}

	//析构函数
	~Shared_Ptr()
	{
		//初始版本
		//if (_pcount == 0)
		//{
		//	delete _pcount;
		//	delete _ptr;
		//}
		//else
		//{
		//	--_pcount;
		//}

		//保证赋值重载能调用析构
		release();
	}

	//拷贝构造
	Shared_Ptr(const Shared_Ptr<T>& sp)
		:_ptr(sp._ptr)
		,_pcount(sp._pcount)
	{
		++(*_pcount);//拷贝后多一个对象管理,引用计数+1
	}


	//实现智能指针
	T& operator*() { return *_ptr; }
	T* operator->() { return _ptr; }

	//获得引用计数个数
	int use_count() { return *_pcount; }

	//返回类中原式指针
	T* get() { return _ptr; }

	void release()
	{
		//当引用计数为1时,不再让该指针管理资源,应该立马释放
		
		//如果是下面这样,当引用计数为1时,只让引用计数-1并没有释放
		//正常情况下引用计数为1时在调用release时就应该delete了
		//if (*_pcount != 0)或者改成!=1
		//{
		//	--(*_pcount);
		//}
		//else
		//{
		//	delete _pcount;
		//	delete _ptr;
		//}
		if (--(*_pcount) == 0)
		{
			delete _pcount;
			delete _ptr;
		}
	}

	//赋值重载--遇见想要多个对象管理时sp1=sp2
	Shared_Ptr<T>& operator=(const Shared_Ptr<T>& sp) 
	{
		//两种情况--1.自己赋值,2.两个不同的赋值
		if (sp._ptr!= _ptr)//不同
		{
			//释放sp1所管理的内容or减去sp1所管理内容的引用计数
			//从引用计数上保证sp1不在管理该块内容
			//调用析构,多套一层release函数
			release();
			_ptr = sp._ptr;
			_pcount = sp._pcount;
			++(*_pcount);
		}
		//else
		//{
		//	return *this;
		//	//相同返回对象本身
		//}
		全部完成后返回对象本身
		//return *this;
		//上述两个return可以合并成一个,在执行完不同对象的赋值后需要返回*this
		//相同时不进入if也返回*this
		return *this;
	}

private:
	int* _pcount;//引用计数个数
	T* _ptr;//管理指针
};

int main()
{
	Shared_Ptr<string> sp1(new string("test_smart_pointer"));
	Shared_Ptr<string> sp2(sp1);//测试拷贝
	cout << "sp1:" << sp1.get() << " _pcount " << sp1.use_count() << endl;//use_count()显示总引用计数
	cout << "sp2:" << sp2.get() << " _pcount " << sp2.use_count() << endl;
	cout << endl;
	Shared_Ptr<string> sp3(new string("test_assignment"));
	sp3 = sp3;//相同赋值
	cout << "sp3:" << sp3.get() << " _pcount " << sp3.use_count() << endl;
	sp1 = sp3;//不同赋值
	cout << "sp1:" << sp1.get() << " _pcount " << sp1.use_count() << endl;
	cout << "sp2:" << sp2.get() << " _pcount " << sp2.use_count() << endl;
	cout << "sp3:" << sp3.get() << " _pcount " << sp3.use_count() << endl;

	return 0;
}

结果:

升级

原代码测试

// 仿函数的删除器
template<class T>
struct FreeFunc {
	void operator()(T* ptr)
	{
		cout << "free:" << ptr << endl;
		free(ptr);
	}
};
template<class T>
struct DeleteArrayFunc {
	void operator()(T* ptr)
	{
		cout << "delete[]" << ptr << endl;
		delete[] ptr;
	}
};
int main()
{
	FreeFunc<int> freeFunc;
	shared_ptr<int> sp1((int*)malloc(4), freeFunc);
	DeleteArrayFunc<int> deleteArrayFunc;
	shared_ptr<int> sp2((int*)malloc(4), deleteArrayFunc);

	return 0;
}

改造模拟实现代码

 重载调用不明确

缺陷

Shared_Ptr<ListNode> sp4(new ListNode[10], DelArray<ListNode>());
Shared_Ptr<ListNode> sp5(new ListNode[10], [](ListNode* ptr) {delete[] ptr; });

sp4->next=sp5;
sp5->prev=sp4;

 

举报

相关推荐

0 条评论