c++构造函数是否可以抛出异常_什么叫抛出异常

c++构造函数是否可以抛出异常_什么叫抛出异常从语法上来说,构造函数和析构函数都可以抛出异常。但从逻辑上和风险控制上,构造函数和析构函数中尽量不要抛出异常,万不得已,一定要注意防止资源泄露。1.构造函数中抛出异常在C++构造函数中,既需要分配内存,又需要抛出异常时要特别注意防止内存泄露的情况发生。因为在构造函数中抛出异常,在概念上将被视为该对象没有被成功构造,因此当前对象的析构函数就不会被调用。同时,由于构造函数本身也是一个函数,在函数体内抛出

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

从语法上来说,构造函数可以抛出异常。但从逻辑上和风险控制上,构造函数中尽量不要抛出异常。万不得已,一定要注意防止内存泄露。

1.构造函数抛出异常导致内存泄漏

在 C++ 构造函数中,既需要分配内存,又需要抛出异常时要特别注意防止内存泄露的情况发生。因为在构造函数中抛出异常,在概念上将被视为该对象没有被成功构造,因此当前对象的析构函数就不会被调用。同时,由于构造函数本身也是一个函数,在函数体内抛出异常将导致当前函数运行结束,并释放已经构造的成员对象,包括其基类的成员,即执行直接基类和成员对象的析构函数。考察如下程序。

#include <iostream>
using namespace std;

class C { 
   
	int m;
public:
	C(){ 
   cout<<"in C constructor"<<endl;}
	~C(){ 
   cout<<"in C destructor"<<endl;}
};

class A { 
   
public:
	A(){ 
   cout<<"in A constructor"<<endl;}
	~A(){ 
   cout<<"in A destructor"<<endl;}
};

class B:public A { 
   
public:
	C c;
	char* resource;

	B() { 
   
		resource=new char[100];
		cout<<"in B constructor"<<endl;
		throw -1;
	}
	~B() { 
   
		cout<<"in B destructor"<<endl;
		delete[]  resource;
	}
};

int main() { 
   
	try { 
   
		B b;
	}
	catch(int) { 
   
		cout<<"catched"<<endl;
	}
}

程序输出结果:

in A constructor
in C constructor
in B constructor
in C destructor
in A destructor
catched

从输出结果可以看出,在构造函数中抛出异常,当前对象的析构函数不会被调用,如果在构造函数中分配了内存,那么会造成内存泄露,所以要格外注意。

此外,在构造对象b的时候,先要执行其直接基类A的构造函数,再执行其成员对象c的构造函数,然后再进入类B的构造函数。由于在类B的构造函数中抛出了异常,而此异常并未在构造函数中被捕捉,所以导致类B的构造函数执行中断,对象b并未构造完成。在类B的构造函数“回滚”的过程中,c的析构函数和类A的析构函数相继被调用。最后,由于b并没有被成功构造,所以main()函数结束时,并不会调用b的析构函数,也就很容易造成内存泄露。

2.使用智能指针管理内存资源

使用 RAII(Resource Acquisition is Initialization)技术可以避免内存泄漏。RAII 即资源获取即初始化,也就是说在构造函数中申请分配资源,在析构函数中释放资源。因为 C++ 的语言机制保证了,当一个对象创建的时候,自动调用构造函数,当对象超出作用域的时候会自动调用析构函数。所以,在 RAII 的指导下,我们应该使用类来管理资源,将资源和对象的生命周期绑定。智能指针是 RAII 最具代表的实现,使用智能指针,可以实现自动的内存管理,再也不需要担心忘记 delete 造成的内存泄漏。

因此,当构造函数不得已抛出异常时,可以利用智能指针 unique_ptr 来防止内存泄露。参考如下程序:

#include <iostream>
using namespace std;

class A { 
   
public:
	A() { 
    cout << "in A constructor" << endl; }
	~A() { 
    cout << "in A destructor" << endl; }
};

class B { 
   
public:
	unique_ptr<A> pA;
	B():pA(new A) { 
   
		cout << "in B constructor" << endl;
		throw - 1;
	}
	~B() { 
   
		cout << "in B destructor" << endl;
	}
};

int main() { 
   
	try { 
   
		B b;
	}
	catch (int) { 
   
		cout << "catched" << endl;
	}
}

程序运行结果:

in A constructor
in B constructor
in A destructor
catched

从程序的运行结果来看,通过智能指针对内存资源的管理,尽管在类B构造函数抛出异常导致类B析构函数未被执行,但类 A 的析构函数仍然在对象 pA 生命周期结束时被调用,避免了资源泄漏。


参考文献

[1] Scott Meyers.More Effective C++[M].北京:电子工业出版社,2013:58-61
[2] 构造函数、析构函数抛出异常的问题
[3] C++中的RAII介绍

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/170085.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 数据库的范式(第一范式,第二范式,第三范式,BCNF范式)「建议收藏」

    在了解范式之前我们先了解下数据库中关于码的概念1.码1.超码能够唯一标识元组的某一属性或属性组,任何包含超码的超集也是超码,这里唯一标识元组可以简单的理解为根据某一个字段或几个字段的值,查询出某一行特定的数据2.候选码从超码中选出的最小的码,即其任何真子集都不能满足条件。即属性不可再删减。3.主码从候选码中选出一个作为主码。2.范式(NF)范式:符合某一种级别的关系模式的集合,简…

    2022年4月16日
    59
  • 免杀工具下载_360免杀器

    免杀工具下载_360免杀器今天有一点想你,其实,不止一点,其实,不止今天。。。​—-网易云热评一、简介快速生成免杀exe可执行文件,目前拥有三种免杀的方法二、下载及安装1、下载到本地gitclonehttps://github.com/lengjibo/FourEye.git2、进入该文件夹cdFourEye3、安装需要的python库pipinstall-rrequirements.txt三、使用方法1、打开该软件python3Byp…

    2022年8月20日
    10
  • 【引用】回发或回调参数无效。在配置中使用 <pages enableEventValidation=”true”/>(转载)…「建议收藏」

    【引用】回发或回调参数无效。在配置中使用 <pages enableEventValidation=”true”/>(转载)…「建议收藏」回发或回调参数无效。在配置中使用<pagesenableEventValidation=”true”/>或在页面中使用<%@PageEnableEventValidation=”true”%>启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用ClientScriptM…

    2022年7月24日
    4
  • 初识数据库

    数据库初步认识什么是数据(Data)什么是数据库(DataBase简称DB)数据库分类:1.关系型数据库2.非关系型数据库关系型数据库:表和表之间相互关联可以建立表(即文件)关系型数

    2022年3月29日
    32
  • JSP的Servlet与Tomcat

    JSP的Servlet与TomcatJSP的Servlet与Tomcat

    2022年4月22日
    38
  • 什么是SOA架构?

    什么是SOA架构?一.SOA的概念1.1.SOA(Service-OrientedArchitecture)面向服务的架构:Gartnet把它定义为一种软件的设计方法 百度百科把它定义为一个组件模型 W3C把它定义为一种应用程序架构(https://www.w3school.com.cn/w3c/w3c_china.asp) 专家Davis说它是一种设计思想 总之,SOA不是具体的技术实现SOA的实现SOA实现层面包含两个最重要的概念:面向服务的通信(SOCService-Oriented…

    2022年6月16日
    31

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号