【问题标题】:why does overload operator= makes exception safety为什么重载运算符 = 使异常安全
【发布时间】:2017-01-01 17:34:31
【问题描述】:

非常直接的问题。

class Bitmap {...};
class Widget {
    ... 
    private:
        Bitmap* pb; 
};

当重载复制赋值时,书(Effective C++)说:下面的代码是异常安全的。

Widget& Widget::operator=(const Widget& rhs) {
    if (rhs == *this) return;
    Bitmap* pOrig = pb; //?? why remember the pb can do exception safety?
    pb = new Bitmap(*rhs.pb);
    delete pOrig;
    return *this;
  }

书上说:即使通过new Bitmap(*rhs.pb)遇到异常,上面的代码也可以做到异常安全,pb可以保持不变,不是指针指向NULL?但是如何,为什么?有人可以帮忙我?谢谢!

【问题讨论】:

  • 是这本书的确切内容吗?这听起来不像是那种可以通过编辑完成的文本。如果可能,请引用确切的文字
  • 什么样的异常安全?强的?基本的?没有?
  • 我怀疑这本书说的是&rhs == this,而不是rhs == *this
  • 是的!是我的错!谢谢!

标签: c++ exception


【解决方案1】:

虽然这个问题可能不太准确,但我想我还是明白了这一点:

想象一下,代码应该是这样写的:

Widget& Widget::operator=(const Widget& rhs)
{
    if (rhs == *this) // actually, you'd rather do &rhs == this!
                      // you don't want self-assignment
        return;
    delete pb;
    pb = new Bitmap(*rhs.pb);
    return *this;
}

如果new Bitamp() 因异常而失败 - 然后 pb 已被删除 - 并指向无效内存,会发生什么!

所以你首先记住了 pb 的值,如果创建失败并出现异常,你还没有修改 this 并且它仍然有效即使如果发生了异常。

【讨论】:

    【解决方案2】:

    如果在new Bitmap(*rhs.pb)的构造过程中抛出异常,Widget的状态仍然保持不变。

    如果您只是在执行new Bitmap(*rhs.pb) 之前删除pb

    Widget& Widget::operator=(const Widget& rhs) {
        if (rhs == *this) return;
        delete pb; // unsafe
        pb = new Bitmap(*rhs.pb);
        return *this;
      }
    

    new Bitmap(*rhs.pb) 失败(抛出异常),Widget 内部不再有Bitmap 实例,pb 指向已删除的Bitmap 实例。这将在销毁Widget 期间崩溃。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-06
      相关资源
      最近更新 更多