首页
学习
活动
专区
圈层
工具
发布

是否能在构造函数,析构函数中抛出异常?

首先是析构函数。 一.  析构函数      参照《Effective C++》中条款08:别让异常逃离析构函数。    总结如下:      1. 不要在析构函数中抛出异常!...虽然C++并不禁止析构函数抛出异常,但这样会导致程序过早结束或出现不明确的行为。      2. 如果某个操作可能会抛出异常,class应提供一个普通函数(而非析构函数),来执行该操作。...构造函数中抛出异常,会导致析构函数不能被调用,但对象本身已申请到的内存资源会被系统释放(已申请到资源的内部成员变量会被系统依次逆序调用其析构函数)。      2....因为析构函数不能被调用,所以可能会造成内存泄露或系统资源未被释放。      3. 构造函数中可以抛出异常,但必须保证在构造函数抛出异常之前,把系统资源释放掉,防止内存泄露。(如何保证???...构造函数中尽量不要抛出异常,能避免的就避免,如果必须,要考虑不要内存泄露! 2. 不要在析构函数中抛出异常! 本文参考: 1. 《Effective C++》条款08:别让异常逃离析构函数。 2.

4K50

dotnet C# 如果在构造函数抛出异常 析构函数是否会执行

假设在某个类型的构造函数里面抛出了异常,那么这个对象的析构函数是否会执行 如下面代码 private void F1() { try...,或者说在构造函数里面抛出异常,是否这个对象可以被垃圾回收 试试以下代码,然后在 ~Foo 添加断点 static void Main(string[] args) {...原因是在 .NET 运行时,是先创建出对象,然后再调用对象的构造函数。...而在创建出对象时,此对象就需要被加入垃圾回收,加入垃圾回收,自然就会调用到析构函数 那为什么即使在构造函数里面抛出异常,没有构造成功,也需要在垃圾回收调用析构函数。...是因为构造函数也不一定是一句话都没有跑的,例如在构造函数里面已分配了一些非托管的内存,然后再抛出异常,自然就期望在析构函数可以释放分配的内存,也就是期望调用析构函数 本文代码还请到 github 或 gitee

62920
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    C++构造函数和析构函数中抛出异常的注意事项

    从语法上来说,构造函数和析构函数都可以抛出异常。但从逻辑上和风险控制上,构造函数和析构函数中尽量不要抛出异常,万不得已,一定要注意防止资源泄露。在析构函数中抛出异常还要注意栈展开带来的程序崩溃。...因为在构造函数中抛出异常,在概念上将被视为该对象没有被成功构造,因此当前对象的析构函数就不会被调用。...由于在类B的构造函数中抛出了异常,而此异常并未在构造函数中被捕捉,所以导致类B的构造函数的执行中断,对象b并未构造完成。在类B的构造函数“回滚”的过程中,c的析构函数和类A的析构函数相继被调用。...最后,由于b并没有被成功构造,所以main()函数结束时,并不会调用b的析构函数,也就很容易造成内存泄露。 2.析构函数中抛出异常 在析构函数中是可以抛出异常的,但是这样做很危险,请尽量不要这要做。...在栈展开的过程中就会调用已经在栈构造好的对象的析构函数来释放资源,此时若其他析构函数本身也抛出异常,则前一个异常尚未处理,又有新的异常,会造成程序崩溃。

    2.7K10

    【C++】构造函数初始化列表 ② ( 构造函数 为 初始化列表 传递参数 | 类嵌套情况下 的 构造函数 析构函数 执行顺序 )

    一、构造函数 为 初始化列表 传递参数 1、构造函数参数传递 构造函数 初始化列表 还可以使用 构造函数 中的参数 ; 借助 构造函数 中的参数列表 , 可以为 初始化列表 传递参数 ; 在下面的代码中...0; } 执行结果 : 二、类嵌套情况下 的 构造函数 / 析构函数 执行顺序 ---- 1、构造函数 / 析构函数 执行顺序 类 B 中 定义了 A 类型 的 成员变量 ; A 类型对象 是 被组合对象...初始化列表 的顺序 进行初始化 ; 析构函数执行顺序 : 析构函数 与 构造函数 的执行顺序 相反 ; 2、代码示例 - 构造函数执行顺序 下面的代码中 , 在 B 类中定义 A 类型 成员变量 ;...执行构造函数时 , 先调用 A 的构造函数 , 再调用 B 的构造函数 ; 执行析构函数时 , 与构造函数顺序相反 , 先执行 B 的析构函数 , 再执行 A 的析构函数 ; 代码示例 : #include...执行 B 的析构函数 执行 A 的析构函数

    91230

    构造函数为什么一般不定义为虚函数?而析构函数一般写成虚函数的原因 ?

    浏览量 3 1、构造函数不能声明为虚函数 1)因为创建一个对象时需要确定对象的类型,而虚函数是在运行时确定其类型的。...而在构造一个对象时,由于对象还未创建成功,编译器无法知道对象的实际类型,是类本身还是类的派生类等等 2)虚函数的调用需要虚函数表指针,而该指针存放在对象的内存空间中;若构造函数声明为虚函数,那么由于对象还未创建...,还没有内存空间,更没有虚函数表地址用来调用虚函数即构造函数了 2、析构函数最好声明为虚函数,首先析构函数可以为虚函数,当析构一个指向派生类的基类指针时,最好将基类的析构函数声明为虚函数,否则可以存在内存泄露的问题...如果析构函数不被声明成虚函数,则编译器实施静态绑定,在删除指向派生类的基类指针时,只会调用基类的析构函数而不调用派生类析构函数,这样就会造成派生类对象析构不完全。子类析构时,要调用父类的析构函数吗?...析构函数调用的次序时先派生类后基类的。和构造函数的执行顺序相反。并且析构函数要是virtual的,否则如果用父类的指针指向子类对象的时候,析构函数静态绑定,不会调用子类的析构。

    84410

    【C++】匿名对象 ③ ( 函数返回值为对象值时 匿名对象 的 拷贝构造函数 与 析构函数 调用情况分析 )

    ; 再后 , 函数执行完毕 , 普通对象 需要被 销毁 , 此时调用析构函数 , 销毁 普通对象 ; 2、处理 函数返回的匿名对象 函数返回的匿名对象 有两种方案 : 为 刚定义 变量 初始化 : 此时直接...执行结果如下 : 调用带参数构造函数 m_age = 18 调用带参数构造函数 m_age = 12 调用拷贝构造函数 调用析构函数 : m_age = 12 调用析构函数 : m_age = 12...匿名对象 ; 调用析构函数 : m_age = 12 这是 fun 函数执行完毕 , 在函数作用域中的 普通对象 需要被析构销毁 ; 调用析构函数 : m_age = 12 这是在 main 函数中..., 使用 匿名对象 为 普通变量赋值 , 需要将 匿名对象的值赋值给普通对象 , 匿名对象 之后直接销毁 , 这是调用析构函数 销毁 fun 函数返回的匿名对象 ; 学生信息 : 年龄 = 12 , 身高..."); return 0; } 执行结果 : 调用带参数构造函数 m_age = 18 调用带参数构造函数 m_age = 12 调用拷贝构造函数 调用析构函数 : m_age = 12 调用析构函数

    98720

    【C++】Chapter02 内存管理

    同时,对于内置类型不会自动调用构造函数和析构函数,需要自己显式调用。...分配内存后,会自动调用构造函数完成对象的构造。 如果 new 分配失败,会抛出 std::bad_alloc 异常(除非使用 new(std::nothrow))。...new 先分配内存,后调用构造函数,保证对象有空间可用。 delete 先调用析构函数,后释放内存,防止析构函数访问已释放的内存。...,new不需要,new将会捕获异常 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间 后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理...系统资源泄漏 程序使用系统分配的资源,比如文件描述符、管道等,没有使用相应的函数释放。 如何检测内存泄漏 使用编译器自带的内存泄漏检测函数,但一般只能检测出大致信息,无法给定较为准确的位置信息。

    12610

    《Effective C++》读书笔记(2):构造析构赋值运算

    /析构函数;生成的析构函数是非虚的,除非基类有虚析构函数。...class SomeClass: private Uncopyable{ ... }; ---- 条款7、为多态基类声明virtual析构函数 C++中多态性质体现于虚函数:基类指针或引用调用虚函数时会检查指向的对象是基类还是派生类...如果析构函数可以抛出异常,那么清空局部资源时局部对象的析构函数再次异常时同时存在两个异常,C++无法处理,可能会过早结束或出现不明确行为。...因此,析构函数绝对不要抛出异常,应通过try-catch捕获任何异常。 有时,客户需要处理某些异常,那么类应该提供一个普通成员函数执行相关操作,供用户调用并处理异常。...virtual函数 C++的构造过程是先构造基类再构造子类、先初始化再进入构造函数体;析构过程相反。

    25030

    【CC++】图文题目吃透内存管理

    ,delete会调用析构函数,而malloc与free不会 new调用构造函数和delete调用析构函数,这很大程度方便了我们,比如构造一个链表: struct ListNode { ListNode...2.自定义类型 new的原理 1.调用operator new函数申请空间 2.在申请的空间上执行构造函数,完成对象的构造 delete的原理 1.在空间上执行析构函数,完成对象中资源的清理工作...new(p2)A(1); p2->~A();//析构函数可以显示调用 free(p2); return 0; } 与new不同的是:new失败会抛出异常,如果不想抛出异常,那就可以用malloc...NULL,使用时必须判断是否为空,new不需要,new需要捕获异常 6.申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数和析构函数,而new在申请空间后会调用构造函数完成对象的初始化...,delete在释放空间前会调用析构函数完成空间中的资源的清理。

    1.2K20

    智能指针在面试中得重要地位!

    operator bool() unique_ptr 指针可直接作为 if 语句的判断条件,以判断该指针是否为空,如果为空,则为 false;反之为 true。...//注意自定义析构器可能是函数对象,函数对象可以包含任意数量的数据,这意味着它们的尺寸可能是任意大小 //std::shared_ptr如何能够在不使用更多内存的前提下,指涉到任意尺寸的析构器?...1,裸指针:如A 被析构,C仍然指涉到 B,B将保存着 指涉到 A的空悬指针,B却检测不出来,所以B 可能无意中提领这个空悬指针 2,std::shared_ptr :AB环路保持,阻止了 A和B被析构...,两者始终保持彼此的引用计数为 1 ,资源得不到回收,内存泄漏 3,std::weak_ptr:避免上述两个问题,如 A被析构,B的回指指针将会空悬,B能检测到这一点。...Widget对象析构数据成员 Widget1::~Widget1(){ delete pImpl; } //C++11 不需要析构函数了 //复制构造函数 Widget1::Widget1(

    1.2K20

    七、构造函数与析构函数

    : value(v) { // 使用初始化列表来初始化成员变量 // 构造函数的主体(在这里是空的) } // 另一个构造函数(无参构造函数) MyClass...析构函数不应该抛出异常(除非有特殊的异常处理策略),因为如果在析构函数中抛出异常且没有被捕获,程序会被终止。...析构函数的调用顺序与构造函数的调用顺序相反。 资源释放: 析构函数通常用于释放对象在生命周期中分配的资源,如动态内存、文件句柄等。 如果析构函数抛出异常且没有被捕获,程序会被终止。...因此,析构函数中应尽量避免抛出异常。 总结 构造函数和析构函数是C++中用于管理对象生命周期的特殊成员函数。...特点: 如果在类中未显式定义任何构造函数,编译器会自动生成一个无参的默认构造函数。 一旦用户显式定义了构造函数(无论是否有参数),编译器将不再自动生成默认构造函数。

    47310

    【C++】继承 ⑥ ( 继承中的构造函数和析构函数 | 类型兼容性原则 | 父类指针 指向 子类对象 | 使用 子类对象 为 父类对象 进行初始化 )

    ” 赋值兼容性原则 " ; 子类代替父类 : 需要 基类 ( 父类 ) 对象的 地方 , 都可以使用 " 公有继承 " 的 派生类 ( 子类 ) 对象 替代 , 该 派生类 ( 子类 ) 得到了 除 构造函数...和 析构函数 之外的 所有 成员变量 和 成员方法 ; 功能完整性 : " 公有继承 " 的 派生类 ( 子类 ) 本质上 具有 基类 ( 父类 ) 的 完整功能 , 使用 基类 可以解决的问题 ,...; 2、类型兼容性原则应用场景 " 类型兼容性原则 " 应用场景 : 直接使用 : 使用 子类对象 作为 父类对象 使用 ; 赋值 : 将 子类对象 赋值给 父类对象 ; 初始化 : 使用 子类对象 为...父类对象 初始化 ; 指针 : 父类指针 指向 子类对象 , 父类指针 值为 子类对象 在 堆内存 的地址 , 也就是 将 子类对象 地址 赋值给 父类类型指针 ; 引用 : 父类引用 引用 子类对象...); } 2、使用 子类对象 为 父类对象 进行初始化 定义父类对象 , 可以直接使用 子类对象 进行初始化操作 ; // II.

    1.3K20

    【笔记】《Effective C++》条款1-25

    C++11后加入了=delete操作, 让我们可以明确删除某些函数的生成 7 为多态基类声明virtual析构函数 对所有多态基类来说, 声明虚析构函数非常重要, 这是因为派生类如果被基类指针指着, 然后被...STL的所有容器都没有虚函数 C++11后引入了final关键字可以用来中断类后续的继承行为 当程序在析构的时候, 会从最深处开始析构, 逐步调用析构函数, 因此基类的虚析构需要一个定义, 可以是空定义...8 别让异常逃离析构函数 由于在C++中两个异常同时存在会导致未定义行为, 因此我们不应该让析构函数上报异常, 这是因为析构函数是会被自动调用的, 当一个对象析构而抛出异常时, 同个作用域的其它对象的析构也会被自动执行...close函数来执行和析构同样的行为, 这样用户就能自己处理可能发生的析构的异常, 同时依然要给真正的析构用try-catch包裹起到双保险的作用 9 绝不在构造和析构过程中调用virtual函数 派生类构造期间...析构函数尽管调用顺序相反但是思路一致 所以不要在析构/构造过程中调用虚函数 补偿方法是将需要让派生类执行的函数以非虚函数的形式写好, 然后将其所需的变量通过构造函数在构造初值列中进行传递.

    1.3K30

    c++类和继承面试点25连问

    析构函数是否可以为虚函数?如果可以,有什么作用? 析构函数可以是虚函数,因为它是对象结束时才调用,不影响虚表构建。...因为销毁的时候直接销毁的基类指针,此时编译器只知道调用基类析构,并不会主动去调用派生类的析构函数,所以基类析构函数需为虚析构函数,这样运行时程序才会去调用派生类的析构函数,其实这就相当于析构函数的多态,...构造函数里面是否可以抛出异常? 构造函数可以抛出异常,若有动态分配内存,则要在抛异常之前手动释放。...析构函数是否可以抛异常 可以,但是最好不要抛出,如果一定要抛出,那要在析构函数内部处理,保证析构函数能执行完成。 16....空类是多大? 由成员变量和是否有虚函数决定,如果类中有虚函数,那就在所有成员变量的基础上加上一个虚函数指针的大小,在64位机器中,虚函数指针为8个字节,注意计算类大小的时候要考虑字节对齐的问题。

    1.1K10

    【智能指针】—— 我与C++的不解之缘(三十三)

    在异常学习中,我们的解决方法就是在test函数中捕获Divide函数抛出的异常,进行资源的释放再将异常重新抛出。...,我们申请的资源都能成功释放(因为arr1和arr2出了作用域就调用析构函数,就会对资源进行释放) 智能指针思想 通过观察上述代码,我们可以发现一个问题:如何访问动态资源呢?...(这样我们就可以直接对智能指针对象进行判断是否为空)。...对于构造函数,首先就是默认构造,我们直接将_ptr和_pcount赋值为nullptr即可。...sp; 我们再让this指向的_ptr和_pcount和sp进行一下交换,这样出了拷贝赋值函数,sp会自动调用析构函数; 这样我们只需要在析构函数内部实现处理资源的操作就OK了。

    15010

    C++打怪升级(七)- 动态内存管理

    class A { public: A(int a = 1) :_a(a) { cout 构造函数: A(int a)" << endl; } ~A() { cout 析构函数...class A { public: A(int a = 1) :_a(a) { cout 构造函数: A(int a)" << endl; } ~A() { cout 析构函数...对于有显式析构函数的自定义类型来说,这也是其调用析构函数次数的依据; class A { public: A(int a = 1) :_a(a) { cout 构造函数: A(int a)...*, 使用时必须强转;new后跟的空间的类型可以直接得到空间类型,不强转 malloc申请空间失败时,返回的是NULL,使用前必须判空;new失败则是抛出异常,可以由另一部分捕获 对于自定义类型对象空间的申请...,malloc/free只开辟空间和释放空间,不会调用构造函数与析构函数(没有初始化);new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理 --

    1.3K10

    智能指针--C++

    智能指针支持在构造时给一个删除器,所谓删除器本质就是一个可调用对象,这个可调用对象中实现你想要的释放资源的方式,当构造智能指针时,给了定制的删除器,在智能指针析构时就会调用删除器去释放资源。...if判断是否为空。...⽀持的 // 这⾥没有使⽤相同的⽅式还是挺坑的 // 使⽤仿函数unique_ptr可以不在构造函数传递,因为仿函数类型构造的对象直接就可以调⽤ // 但是下⾯的函数指针和lambda的类型不可以..._ptr = nullptr; } auto_ptr& operator=(auto_ptr& ap) { // 检测是否为⾃⼰给⾃⼰赋值 if (this !...(了解) linux下内存泄漏检测:linux下几款内存泄漏检测工具 windows下使用第三方工具:windows下的内存泄露检测工具VLD使用_windows内存泄漏检测工具 九、如何避免内存泄漏

    19200

    C++内存管理深度总结(近万字详解!)

    它们与C语言中的malloc和free有相似之处,但专为C++对象设计,能够与构造函数和析构函数协同工作。...它们的实现原理涉及到底层的内存管理机制,以及 C++ 构造函数和析构函数的调用。...对于类类型的对象,这意味着会调用类的析构函数,并执行析构函数中定义的清理逻辑。...,因为我们没有使用普通的 new 来分配它 return 0; } 【注意】: 显式析构:使用 placement-new 构造的对象,必须显式调用它们的析构函数。...申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初给化,delete在释放空间前会调用析构函数完成空间中资源的清理。

    41310

    C++传送锚点的内存寻址:内存管理

    delete相对于free会进行严格的类型检查,确保释放的是new开辟的空间,而且会调用析构函数 值得注意的是: 申请和释放单个元素的空间,使用new和delete操作符;申请和释放连续的空间,使用...的调用顺序 调用operator new开辟空间 调用构造函数 调用析构函数 调用operator delete释放空间 2.3 定位new表达式 class A { public: A(int a.../free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理 3.2 内存泄漏 什么是内存泄漏?...内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费 如何检测内存泄漏?...* p = new int[10]; // 将该函数放在main函数之后,每次程序退出的时候就会检测是否存在内存泄漏 _CrtDumpMemoryLeaks(); return 0; } // 程序退出后

    22410
    领券