检查operator =中的自我赋值

Nat*_* S. 2 c++ operator-overloading

我正在查看第五版C++ Primer中的代码示例.在页512上,他们提供operator=如下示例代码:

HasPtr& HasPtr::operator=(const HasPtr &rhs)
{
    auto newp = new string(*rhs.ps); // copy the underlying string
    delete ps;                       // free the old memory
    ps = newp;                       // copy data from rhs into this object
    i = rhs.i;
    return *this;                    // return this object
}
Run Code Online (Sandbox Code Playgroud)

他们正确地争辩说,如果按照这个顺序做事,即使是自我分配,事情也会正常.但是,我一直看到检查是明确完成的建议:

HasPtr& HasPtr::operator=(const HasPtr &rhs)
{
    if (&rhs == this) return *this;  // early exit if self assignment

    auto newp = new string(*rhs.ps); // copy the underlying string
    delete ps;                       // free the old memory
    ps = newp;                       // copy data from rhs into this object
    i = rhs.i;
    return *this;                    // return this object
}
Run Code Online (Sandbox Code Playgroud)

这避免了额外的内存分配/释放步骤.

任何人都可以解释为什么他们强调编写处理自我分配的代码而不是仅仅提前退出自我分配?

Jon*_*ely 5

我一直看到建议明确完成检查

您一直在寻找错误的地方,例如Sutter和Alexandrescu的C++ Coding Standards.

在大多数程序中,自我分配极为罕见,因此即使检查几乎总是假的,显式检查也会为每个自我分配增加一小笔费用.如果你写你的赋值运算符是正确的,即使在自赋值的情况,那么你不要在绝大多数情况下的检查费用,如果自赋值发生它仍然有效.

Sutter和Alexandrescu展示了一个根据swap成员编写的赋值运算符:

Foo& operator=(const Foo& other)
{
  Foo(other).swap(*this);
  return *this;
}
Run Code Online (Sandbox Code Playgroud)

这样可以安全地防止自我赋值,异常安全并重新使用复制构造函数,因此您不必显式实现赋值.