std::shared_ptr与异常

1.使用std::shared_ptr避免函数异常退出而导致的内存泄漏

如下代码:

void funSharePtr(int a, int b)
{
	std::shared_ptr<int> p(new int(10));
	// 做一些操作
	if (...) {
		throw (std::exception("Error")); // 抛出异常且本函数没有捕获该异常
	}

	// ...其他操作
}

对于funSharePtr如果该函数异常退出,所有的局部变量都将被析构,因此智能指针p中指向的内存也会被智能指针释放掉

void funPtr(int a, int b) 
{
	int* p = new int(10);
	// 做一些操作
	if (...) {
		throw (std::exception("Error")); // 抛出异常且本函数没有捕获该异常
	}

	// ...其他操作

	delete p; // 释放p
}

对于funPtr,如果该函数异常退出,导致执行不到delete语句,发生内存泄漏

因此std::shared_ptr可以有效的避免因函数异常退出导致的内存泄漏。

2自定义删除器

对于一些c代码定义的结构体,没有为其定义自动释放资源的函数(析构函数),因此即使结构体退出作用域被释放掉后,资源也不一定被正确的释放掉:

struct Con connect(const char* addr); // 连接某个地址 并返回一个连接对象
void disconnect(Con* con);            // 断开链接 释放连接资源(如套接字)

void f(const char* addr)
{
	Con con = connect(addr);
	// 使用con做一些事 ...

	if (...) {
		throw std::exception("Error"); // 抛出异常
	}

	disconnect(&con);
}

以上代码中,如果抛出异常,即使con是局部对象,函数异常退出也会被释放掉,但其并没有释放连接的资源,因为没有调用disconnect函数,此时同样会发生资源泄漏。

可以为std::shared_ptr自定义删除器替代delete操作,并进行资源释放的操作:

void f(const char* addr)
{
	Con con = connect(addr);
	// 定义了一个lambda作为删除器替代delete操作,参数类型要与p中指向的内存的类型一致
	std::shared_ptr<Con> p(&con, [](Con* c) {disconnect(c); });

	// 使用p做一些事 ...

	if (...) {
		throw std::exception("Error"); // 抛出异常
	}
}

以上代码在正常退出或者异常退出时,均会执行disconnect函数,释放资源,此时std::shared_ptr并不会执行delete函数。
由此可见,对于栈上的变量,也可为其使用std::shared_ptr,但要确保其不会执行delete函数。

3关于智能指针的陷阱:

1.不要使用相同的普通指针来初始化多个std::shared_ptr
2.慎用get()函数
3.使用std::shared_ptr管理并非new出来的对象时,要指定删除器,以防止delete操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值