Guru of the Week #8 具有挑战性的话题:异常安全(exception safety)[2]

[入库:2005年8月18日] [更新:2007年3月25日]

本文简介:选择自 plpliuly 的 blog

        void     push(const t&);
        t        pop();     // if empty, returns default-
                            // constructed t

    private:
        t*       v_;        // pointer to a memory area big
                            //  enough for 'vsize_' t objects
        unsigned vsize_;    // the size of the 'v_' area
        unsigned vused_;    // the number of t's actually
                            //  used in the 'v_' area
    };
  
   现在开始讨论实现。首先我们对于t有一个要求:就是t的析构函数必须不能抛出异常。如果析构函数可以抛出异常,要安全的实现许多操作就会是非常的困难甚至是不可能的。


//----- default ctor ----------------------------------------------
template<class t>
stack<t>::stack()
  : v_(new t[10]),  // 缺省的内存分配
    vsize_(10),
    vused_(0)       // 还没有使用任何内存
{
    // 如果程序执行到此,构造函数就成功了
}

//----- copy ctor -------------------------------------------------
template<class t>
stack<t>::stack( const stack<t>& other )
  : v_(0),      // nothing allocated or used yet
    vsize_(other.vsize_),
    vused_(other.vused_)
{
    v_ = newcopy( other.v_, other.vsize_, other.vsize_ );
    // 如果程序执行到此, 拷贝构造函数就成功了
}

//----- copy assignment -------------------------------------------
template<class t>
stack<t>& stack<t>::operator=( const stack<t>& other )
{
    if( this != &other )
    {
        t* v_new = newcopy( other.v_, other.vsize_, other.vsize_ );
        //如果程序执行到此, 内存分配和拷贝就成功了

        delete[] v_;
        // 注意这条语句不能抛出异常,因为t的析构函数不会抛出异常
        // 而delete操作符声明为throw()

        v_ = v_new;
        vsize_ = other.vsize_;
        vused_ = other.vused_;
    }

    return *this;   // 安全,不涉及拷贝
}

//----- dtor ------------------------------------------------------
template<class t>
stack<t>::~stack()
{
    delete[] v_;    // 此处同样不会抛出异常
}

//----- count -----------------------------------------------------
template<class t>
unsigned stack<t>::count()
{
    return vused_;  // 这是一个原生类型,不会导致异常
}

//----- push ------------------------------------------------------
template<class t>
void stack<t>::push( const t& t )
{
    if( vused_ == vsize_ )  // grow if necessary
    {
        unsigned vsize_new = (vsize_+1)*2; // grow factor
        t* v_new = newcopy( v_, vsize_, vsize_new );
        file://如果程序执行到此, 内存分配和拷贝就成功了

        delete[] v_;    // 此处同样不会抛出异常
        v_ = v_new;
        vsize_ = vsize_new;
    }

    v_[vused_] = t; // 如果拷贝操作抛出异常,
    ++vused_;       // 因为vused_并没有增长,所以状态没有改变

本文关键:异常安全(exception safety) 异常中立(exception-neutral)
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top