2021-04-15

本文探讨了C++中在构造函数和析构函数中抛出异常的情况。当构造函数抛出异常时,已分配的内存会自动释放,但析构函数不会被调用。而在重载的new操作符中抛出异常会导致内存无法正确释放,造成内存泄漏。最后的例子展示了在构造函数中动态分配内存并抛出异常时,动态对象不会被删除,可能导致资源泄露。因此,建议在构造函数中进行资源管理,并在异常发生前释放已分配的资源。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、c++析构函数中抛出异常

(1)下面是简单构造函数抛出异常:

#include <iostream>

using namespace std;

class Inner

{
public:

Inner()

{
cout<<"Inner()/n";

}

~Inner()

{
cout<<"~Inner()/n";

}

};

 

class Outer

{
private:

int m_Value;

Inner inner1;

public:

Outer(int value):m_Value(value)

{
cout<<"Outer(int value)/n";

throw 3;

}

~Outer()

{
cout<<"~Outer()/n";

}

void* operator new(size_t size)

{
cout<<"void* operator new(size_t size)/n";

unsigned char* tmp = ::new unsigned char[size];

return tmp;

}

void operator delete(void* ptr)

{
cout<<"void* operator delete(void* ptr)/n";

::delete[] (unsigned char*)ptr;

}

};

 

main()

{
try

{
Outer* d = new Outer(1);

}

catch(...)

{
cout<<"exception got it/n";

}

}

 

这段代码编译后执行结果:

void* operator new(size_t size)

Inner()

Outer(int value)

~Inner()

void* operator delete(void* ptr)

exception got it

从代码执行结果来看,我们可以得出如下结论:

1.new一个对象有两个过程

 A.向系统申请内存空间  
 B.在申请的内存空间上执行构造函数,初始化对象。

2.内部对象构造先于对象本身。

3.对象在构造函数抛出异常后,系统会负责清理构造对象时申请的内存,但不会调用对象析构函数。

也就是说构造对象的内存会被释放掉,已经完成实例化的成员对象也会成功析构。

通过valgrind工具可以看到不存在内存泄漏。
Alt

(2)第二次修改

下面我们把代码修改一下。修改只有两处,注意标记。



#include <iostream>

using namespace std;

class Inner

{
private:

int m_Value;

public:

Inner()

{
cout<<"Inner()/n";

}

Inner(int value):m_Value(value)

{
cout<<"Inner(int value)/n";

}

~Inner()

{
cout<<"~Inner()/n";

}

};

 

class Outer

{
private:

int m_Value;

Inner inner1;

public:

Outer()

{
cout<<"Outer()/n";

//throw 3;//注意这里注意这里注意这里注意这里

}

Outer(int value):m_Value(value)

{
cout<<"Outer(int value)/n";

}

~Outer()

{
cout<<"~Outer()/n";

}

void* operator new(size_t size)

{
cout<<"void* operator new(size_t size)/n";

unsigned char* tmp = ::new unsigned char[size];

throw 1;//注意这里注意这里注意这里注意这里注意这里

return tmp;

}

void operator delete(void* ptr)

{
cout<<"void* operator delete(void* ptr)/n";

::delete [] (unsigned char*)ptr;

}

};

 

main()

{
try

{
Outer* d = new Outer(1);

}

catch(...)

{
cout<<"got it/n";

}

}

 

**我们改在重载的new操作符方法中抛出异常。**

 

程序输出结果:

void* operator new(size_t size)

got it

 


是的,这个结果想必大家已经预料到了,析构和释放内存的操作都没有执行。

valgrind 的执行结果:
在这里插入图片描述
发生了内存泄漏。

重载new操作符,用户可以在自己的内存池中分配内存去构造对象,但是如果成功申请内存但后续执行抛出异常后,就会造成内存泄漏。

三、最后修改一下代码

还是在构造函数中抛出异常,注意红色标记

#include <iostream>
//该代码中有指针没有被释放。
using namespace std;

class Inner

{
private:

int m_Value;

public:

Inner()

{
m_Value=1;

cout<<"Inner()/n";

}

Inner(int value):m_Value(value)

{
cout<<"Inner(int value)/n";

}

~Inner()

{
cout<<"~Inner"<<m_Value<<"()/n";

}

};

 

class Outer

{
private:

int m_Value;

Inner inner1;

Inner* inner2;

public:

Outer()

{
cout<<"Outer()/n";

}

Outer(int value):m_Value(value)

{
cout<<"Outer(int value)/n";

inner2 = new Inner(2);

throw 1;

}

~Outer()

{
cout<<"~Outer()/n";

}

void* operator new(size_t size)

{
cout<<"void* operator new(size_t size)/n";

unsigned char* tmp = ::new unsigned char[size];

return tmp;

}

void operator delete(void* ptr)

{
cout<<"void* operator delete(void* ptr)/n";

::delete [] (unsigned char*)ptr;

}

};

 

main()

{
try

{
Outer* d = new Outer(1);

}

catch(...)

{
cout<<"got it/n";

}

}
输出结果:
void* operator new(size_t size)

Inner()

Outer(int value)

Inner(int value)

~Inner1()

void* operator delete(void* ptr)

got it

转载自

总结

一个对象在构造函数中抛出异常,对象本身的内存会被成功释放,但是其析构函数不会被调用。其内部局部成员对象清栈时是会被释放掉的,故其析构函数被调用,但是用户在构造函数中动态生成的对象没有被delete掉(new出来的是一个指针,清栈时是不会delete掉栈里的指针)。

如果一个对象在构造函数中打开很多系统资源,但是构造函数中后续代码抛出了异常,则这些资源将不会被释放,建议在构造函数中加入try catch语句,对先前申请的资源进行释放后(也就是做析构函数该做的事情)再次抛出异常,确保内存和其他资源被成功回收。

内容概要:本文围绕“考虑电动汽车聚合可调节能力的含波动性电源电氢耦合系统多目标优化运行”展开研究,提出了一种基于Matlab代码实现的多目标优化模型。该模型深度融合电-氢耦合系统与高比例波动性可再生能源(如风电、光伏),充分挖掘电动汽车(EV)集群作为移动储能单元的灵活调节潜力,通过聚合调控提升系统对新能源的消纳能力与运行经济性。研究系统构建了电动汽车可调度能力、电解水制氢与储氢动态过程、多能源协同互补的优化调度框架,并结合智能优化算法实现经济性、低碳性与运行稳定性等多重目标的协同优化。文中配套提供了完整的Matlab仿真代码、相关数据及可能的论文支撑材料,极大地方便了模型的复现、验证与后续深化研究。; 适合人群:具备电力系统、综合能源系统、优化理论或新能源技术等相关领域基础知识的研究生、科研人员,以及从事新型电力系统规划、清洁能源消纳与智慧能源管理的工程技术人员。; 使用场景及目标:①开展高渗透率可再生能源接入下的综合能源系统多目标优化调度研究;②探究电动汽车集群在电网削峰填谷、平抑新能源出力波动及提供辅助服务方面的应用价值与潜力;③学习并掌握电氢耦合系统的建模方法、多目标优化求解技术及其在Matlab/Simulink环境下的仿真实现流程。; 阅读建议:此资源不仅提供可运行的代码,更蕴含了前沿的科研思路与创新方法,建议读者结合所提供的代码、数据与可能的论文文档,系统性地学习从问题建模、算法设计到仿真分析的完整科研过程,并重点关注其中关于需求侧资源聚合、多能互补协同与绿色低碳运行的核心理念。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值