C++构造函数、析构函数与抛出异常

【本文链接】

http://www.cnblogs.com/hellogiser/p/constructor-destructor-exceptions.html

【问题】

构造函数可以抛出异常么?析构函数可以吗?

【分析】

从语法上来说,构造函数和析构函数都可以抛出异常。但从逻辑上和风险控制上,构造函数可以,析构函数不推荐抛出异常。

(1)构造函数可以抛出异常

无论何时,从构造函数中抛出异常都是可以的。动态创建对象要进行两个操作:分配内存和调用构造函数。若在分配内存时出错,会抛出bad_alloc异常;若在调用构造函数初始化时出错,会不会存在内存泄漏呢?答案是不会。

new运算符保证不会出现内存泄漏:

C++ Code


1
 
T *p = new T;

将被编译器转换给类似下面的样子:

C++ Code


1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
void allocate_and_construct()
{
    // 第一步,分配原始内存,若失败则抛出bad_alloc异常
    try
    {
        // 第二步,调用构造函数构造对象
        new (p)T;       // placement new: 只调用T的构造函数
    }
    catch(...)
    {
        delete p;     // 释放第一步分配的内存
        throw;          // 重抛异常,通知应用程序
    }
}

(2)析构函数不推荐抛出异常,如果析构函数可能抛出异常,那么必须要求在析构函数内消化所有异常或者结束程序。

more effective c++提出两点理由(析构函数不能抛出异常的理由)

1)如果析构函数抛出异常,则异常点之后的程序不会执行,如果析构函数在异常点之后执行了某些必要的动作比如释放某些资源,则这些动作不会执行,会造成诸如资源泄漏的问题。 [正常情况下调用析构函数抛出异常导致资源泄露]

2)通常异常发生时,c++的机制会调用已经构造对象的析构函数来释放资源,此时若析构函数本身也抛出异常,则前一个异常尚未处理,又有新的异常,会造成程序崩溃的问题。 [在发生异常的情况下调用析构函数抛出异常,会导致程序崩溃]

解决方案:

1) 如果某个操作可能会抛出异常,class应提供一个普通函数(而非析构函数),来执行该操作。目的是给客户一个处理错误的机会。

2) 如果析构函数中异常非抛不可,那就用try catch来将异常吞下,必须要把这种可能发生的异常完全封装在析构函数内部,决不能让它抛出函数之外。

【参考】

http://blog.csdn.net/liuxialong/article/details/6586083

http://www.cnblogs.com/fly1988happy/archive/2012/04/11/2442765.html

http://www.cnblogs.com/KevinSong/p/3323372.html

时间: 2024-10-11 05:48:10

C++构造函数、析构函数与抛出异常的相关文章

C++关于构造函数 和 析构函数 能否抛出异常的讨论

构造函数和析构函数分别管理对象的建立和释放,负责对象的诞生和死亡的过程.当一个对象诞生时,构造函数负责创建并初始化对象的内部环境,包括分配内存.创建内部对象和打开相关的外部资源,等等.而当对象死亡时,析构函数负责关闭资源.释放内部的对象和已分配的内存. 在对象生死攸关的地方,如果程序代码出现问题,常常会发生内存泄漏,从而产生可能危害系统运行的孤魂野鬼.大量的事实表明,业务逻辑代码写得非常严谨的程序在运行中仍然发现存在内存泄露,大都是构造和析构部分的代码存在问题. 而许多程序员都习惯于面向对象的编

C\C++ vector 构造函数 & 析构函数

#include <iostream> #include <vector> using namespace std; class Obj { public: Obj(void){cout<<"Obj(void)"<<" "<<countOne<<endl;countOne++;} Obj(int x){cout<<"Obj(int x)"<<"

Item 8:析构函数不要抛出异常 Effective C++笔记

Item 8: Prevent exceptions from leaving destructors. 析构函数不要抛出异常 因为析构函数经常被自己主动调用,在析构函数中抛出的异常往往会难以捕获,引发程序非正常退出或没有定义行为. 比如,对象数组被析构时.会抛出多于一个的异常,然而同一时候存在的异常在C++标准中是禁止的, 因此程序会非正常退出: class Widget { public: ~Widget() { ... } // assume this might emit an exce

C++反汇编第一讲,认识构造函数,析构函数,以及成员函数

C++反汇编第一讲,认识构造函数,析构函数,以及成员函数 以前说过在C系列下的汇编,怎么认识函数.那么现在是C++了,隐含有构造和析构函数 一丶认识构造函数 高级代码: class MyTest { public: MyTest(); ~MyTest(); public: DWORD m_dwTest; }; MyTest::MyTest() { printf("1111\r\n"); //构造的时候先打印 } MyTest::~MyTest() { printf("2222

构造函数失败_抛出异常

网上比较经典的总结: 什么函数都有可能失败,构造函数也不另外,比如new一个对象或空间不成功.当构造函数失败的时候,其实很多时候我们不想这个对象被继续生成,这个时候就可以在构造函数里面抛出异常.C++规定构造函数抛出异常之后,对象将不被创建,析构函数也不会被执行,但已经创建成功的部分(比如一个类成员变量)会被部分逆序析构,不会产生内存泄漏.但有些资源需要在抛出异常前自己清理掉,比如打开成功的一个文件,最好关闭掉再抛出异常(虽然系统也会把这个资源回收),因为抛出异常之后析构函数不会被执行了. (1

【C/C++学院】(6)构造函数/析构函数/拷贝构造函数/深copy浅copy

1.构造函数 类的初始化即为构造函数.也为:隐式的初始化. 构造函数在对象初始化的时候,自动被调用.隐式的调用. 构造函数分为三种:有参构造函数.无参构造函数.拷贝构造函数. 有参构造函数调用有三种:括号法.等号法.手工法. #include <iostream> using namespace std; class Test { private: int m_a; public: Test()//无参构造函数 { } Test(const Test &obj)//拷贝构造函数 { }

C++基础知识---构造函数 &amp; 析构函数 &amp; 虚拟析构函数

问题: 类需要一个无参的构造函数么? 类需要一个析构函数么? 类的构造函数需要初始化所有的对象成员么? 类需要一个虚析构函数么? 有些类需要虚析构函数只是为了声明他们的析构函数是虚的.绝不会用作基类的类是不需要虚析构函数的:任何虚函数只在继承的情况下才有用.假设B为父类,D为子类,B何时需要一个虚析构函数?只有有人肯呢过会对实际指向D类型对象的B*指针执行delete表达式,你就需要给B加上一个虚析构函数,即使B和D都没有虚函数,这也是需要的 B* bp = new D; Delete bp; 

构造函数 析构函数

;构造函数 构造函数和类同名,无类型和返回值 构造函数可以重载 构造函数编译器在对象申请完内存地址空间之后帮你调用,如果有父类先一层层的调完父类的构造函数最后子类 ;析构函数 析构函数只调用一次 析构函数在出对象所属作用域之后立马被调用 析构函数无类型,返回值参数 西沟函数可以外部手工调用 ;拷贝构造函数 拷贝构造函数参数为引用参数 类& object 拷贝构造函数在发生对象拷贝的时候被调用,例如函数传参如果形参是对象类型就会发生,其他类型不会, (const 类& object) 如果实

构造函数 析构函数需要注意的

构造函数和析构函数¶ 构造函数¶ void __construct ([ mixed $args [, $... ]] ) PHP 5 允行开发者在一个类中定义一个方法作为构造函数.具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作. Note: 如果子类中定义了构造函数则不会隐式调用其父类的构造函数.要执行父类的构造函数,需要在子类的构造函数中调用 parent::__construct().如果子类没有定义构造函数则会如同一个普通的类方法一样从父类继