【本文链接】

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

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

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

    构造函数和析构函数分别管理对象的建立和释放,负责对象的诞生和死亡的过程.当一个对象诞生时,构造函数负责创建并初始化对象的内部环境,包括分配内存.创建内部对象和打开相关的外部资源,等等.而当对象死亡时, ...

  2. C++构造函数/析构函数 设置成private的原因

    C++构造函数/析构函数 设置成private的原因 标签(空格分隔): c/c++ 将构造函数,析构函数声明为私有和保护的,那么对象如何创建? 已经不能从外部调用构造函数了,但是对象必须被构造,应该 ...

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

    C++反汇编第一讲,认识构造函数,析构函数,以及成员函数 以前说过在C系列下的汇编,怎么认识函数.那么现在是C++了,隐含有构造和析构函数 一丶认识构造函数 高级代码: class MyTest { ...

  4. C++ 类 & 对象-类成员函数-类访问修饰符-C++ 友元函数-构造函数 & 析构函数-C++ 拷贝构造函数

    C++ 类成员函数 成员函数可以定义在类定义内部,或者单独使用范围解析运算符 :: 来定义. 需要强调一点,在 :: 运算符之前必须使用类名.调用成员函数是在对象上使用点运算符(.),这样它就能操作与 ...

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

    Item 8: Prevent exceptions from leaving destructors. 析构函数不要抛出异常 因为析构函数经常被自己主动调用,在析构函数中抛出的异常往往会难以捕获,引 ...

  6. C++ 中的类构造函数 & 析构函数

    类的构造函数 类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行. 构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void.构造函数可用于为某些成员变量设置 ...

  7. c++基础语法 构造函数 析构函数 类的组合

    1 构造函数 1.不能指定任何返回值,甚至连void都不能有. 2.与Java不同,c++不同new对象,对于无参的构造函数声明对象时括号应该省略. 2 析构函数 1. 前加~,不能有参数,不能有返回 ...

  8. c++类大四个默认函数-构造函数 析构函数 拷贝构造函数 赋值构造函数

    每个类只有一个析构函数和一个赋值函数,但可以有多个构造函数(包含一个拷贝构造函数,其它的称为普通构造函数).对于任意一个类A,如果不编写上述函数,C++编译器将自动为A 产生四个缺省的函数,例如: A ...

  9. c#类 对象 构造函数 析构函数——面向对象

    类: 也是复杂数据类型 也是需要我们先定义出类型,才能使用它的数据 对象: 是通过模板类实例化出来的个体,具有具体的属性和行为(方法),对象是不能索引到静态方法. 对象的生命周期 构造—— 使用—— ...

随机推荐

  1. ASP.NET MVC使用Bootstrap系列(4)——使用JavaScript插件

    阅读目录 序言 Data属性 VS 编程API 下拉菜单(dropdown.js) 模态框(modal.js) 标签页(tab.js) 工具提示(tooltip.js) 弹出框(popover.js) ...

  2. CSS立体标签实现

    <style> .tag { background-color: #de3f33; position: relative; text-align: center; color: #fff; ...

  3. 用svnsync 同步备份 svn 版本库 从一台服务器到另一台服务器

    如用svnsync 同步备份两台机器的svn .(就以linux服务器到windows服务器为例子) 要同步的项目名称:source_svn svn 版本库1 .4 以上 源目录:           ...

  4. jsp应用

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  5. js 的强制 类型 转换cast, 伪对象?

    拼音输入法简单快捷, 但是重码多, 所以要看清了再选择, 不然会影响输入正确性和 心情的! js的类型 隐式 转换? 是指, 根据 表达式的操作符号 如if(), + , && , j ...

  6. Memcached存储命令 - add

    Memcached add 命令用于将 value(数据值) 存储在指定的 key(键) 中. 如果 add 的 key 已经存在,则不会更新数据,之前的值将仍然保持相同,并且您将获得响应 NOT_S ...

  7. 在nodejs下express 从安装到运行的全过程

    安装过程: npm install -gd express  npm install -g express-generator  express -V //查看版本,现在一般都是4.x系列的 expr ...

  8. 网站SEO优化之Robots.txt文件写法。

    作为网站开发者或网站管理员一定知道网站对搜索引擎的优化有多重要,好的网站不仅要有漂亮的界面,良好的用户体验,还要有较高的更新频率.要被百度.google这样的搜索引擎大量收录,才能增加网站展示量,访问 ...

  9. Oracle卸载

    用Oracle自带的卸载程序不能从根本上卸载Oracle,从而为下次的安装留下隐患,所以要想完全卸载Oracle就必须要直接将注册表清除. 步骤如下: 1. 开始->设置->控制面板-&g ...

  10. 随鼠标移动tab

    <script language="javascript">         function tabChange(obj, id) {             var ...