现在的位置: 首页 > 综合 > 正文

防止自己对自己赋值

2013年08月08日 ⁄ 综合 ⁄ 共 964字 ⁄ 字号 评论关闭

     在赋值运算符中要特别注意可能出现别名的情况,其理由基于两点。
     其中之一是效率。如果可以在赋值运算符函数体的首部检测到是给自己赋值,就可以立即返回,从而可以节省大量的工作,否则必须去实现整个赋值操作。例如,条款16指出,一个正确的派生类的赋值运算符必须调用它的每个基类的的赋值运算符,所以在派生类中省略赋值运算符函数体的操作将会避免大量对其他函数的调用。

    另一个更重要的原因是保证正确性。一个赋值运算符必须首先释放掉一个对象的资源(去掉旧值),然后根据新值分配新的资源。在自己给自己赋值的情况下,释放旧的资源将是灾难性的,因为在分配新的资源时会需要旧的资源。

 

    确定对象身份是否相同的方法是用内存地址。采用这个定义,两个对象当且仅当它们具有相同的地址时才是相同的。这个定义在c++程序中运用更广泛,可能
是因为它很容易实现而且计算很快,而采用值相等的定义则不一定总具有这两个优点.

   别名和object identity的问题不仅仅局限在operator=里。在任何一个用到的函数里都可能会遇到。在用到引用和指针的场合,任何两个兼容类型的对象名称都可能指的是同一个对象。下面列出的是别名出现的其它情形:

class base {
   void mf1(base& rb);          // rb和*this可能相同                     
  ...

};

void f1(base& rb1,base& rb2);  // rb1和rb2可能相同
                               //
class derived: public base {
  void mf2(base& rb);          // rb和*this可能相同
                               //
  ...

};

int f2(derived& rd, base& rb); // rd和rb可能相同
                               //

这些例子刚好都用的是引用,指针也一样。

可以看到,别名可以以各种形式出现,所以决不要忘记它或期望自己永远不会碰到它。也许你不会碰到,但我们大多数会碰到。而很明显的一条是,处理它会达到事半功倍的效果。所以任何时候写一个函数,只要别名有可能出现,就必须在写代码时进行处理。

抱歉!评论已关闭.