zoukankan      html  css  js  c++  java
  • Item 39. 异常安全之函数(Exception Safe Functions)

    Item 39. Exception Safe Functions

    编写异常安全代码的难点不在于抛出和捕获异常,而是在于抛出和捕获之间要做的事情。当异常从抛出

    到达捕获语句的过程中,这期间执行的函数在弹栈前需要清理它所使用的任何资源。通常,这就需要片

    刻的思考以及一些常识。

    以String的赋值操作为例:
     
    String &String::operator =( const char *str ) {
        if( !str ) str = "";
        char *tmp = strcpy( new char[ strlen(str)+1 ], str );
        delete [] s_;
        s_ = tmp;
        return *this;
    }

    char *tmp 这个中间变量似乎有点多余,我们“可以”写成这样:
    String &String::operator =( const char *str ) {
        delete [] s_;                                       
        if( !str ) str = "";
        s_ = strcpy( new char[ strlen(str)+1 ], str );
        return *this;
    }

    果真如此吗?
    delete [] 根据约定可以保证不抛出异常,然而new[]可能抛出异常。在未知新的内存是否分配成功的

    时候,我们却把s_的内存释放掉了。于是,String对象处于一个bad state。
    Herb Sutter 告诉我们在这种情况下应该这样处理:首先在不改变重要状态的一边处理那些能够引发异

    常的操作,而后用不能引发异常的操作结束整个过程(First do anything that could cause an

    exception "off to the side" without changing important state, and then use operations that

    can't throw an exception to finish up.)。

    再看一例:

    错误的写法:
    void Button::setAction( const Action *newAction ) {             
        delete action_; // change state!                            
        action_ = newAction->clone(); // then maybe throw?          

    繁琐的写法:
    void Button::setAction( const Action *newAction ) {             
        delete action_;                                             
        try {                                                       
            action_ = newAction->clone();                           
        }                                                           
        catch( ... ) {                                              
            action_ = 0;                                            
            throw;                                                  
        }                                                           
    }  

    简单正确的写法:
    void Button::setAction( const Action *newAction ) {
        Action *temp = newAction->clone(); // off to the side...
        delete action_; // then change state!
        action_ = temp;
    }

  • 相关阅读:
    CentOS6设置密码过期时间
    scp
    windows查看进程
    mysql5.7密码问题
    mysql主从切换摘要
    mysql慢日志管理
    Linux学习(一)
    Linux学习(一)
    数据结构与算法(1)-算法时间复杂度
    数据结构与算法(1)-算法时间复杂度
  • 原文地址:https://www.cnblogs.com/aiwz/p/6333205.html
Copyright © 2011-2022 走看看