我对这个赋值操作符错误的假设是正确的吗?

Am I correct in my assumption about an error on this assignment operator?

本文关键字:假设 赋值操作符 错误      更新时间:2023-10-16

Richard Gillam在他的"The Anatomy of The Assignment Operator"中,在他论文的开头说了下面这段话,他可能说错了:

"这个问题的正确答案应该是这样的:"

TFoo&TFoo::operator=(const TFoo& that)
{
    if (this != &that)
    {
        TBar* bar1 = 0;
        TBar* bar2 = 0;
        try
        {
            bar1 = new TBar(*that.fBar1);
            bar2 = new TBar(*that.fBar2);
        }
        catch (...)
        {
            delete bar1;
            delete bar2;
            throw;
        }
        TSuperFoo::operator=(that);
        delete fBar1;
        fBar1 = bar1;
        delete fBar2;
        fBar2 = bar2;
    }
    return *this;
}

我认为作者错了,因为如果TSuperFoo::operator=()抛出,bar1bar2将会泄漏。

如果看起来像这样,就不会有内存泄漏:

Tbar* pBar = NULL;
try
{
    pBar = new Tbar();
}
catch (...)
{
    delete pBar;    // clean memory if it was allocated
    throw;          // error was not handled properly, throw it to caller
}
delete pBar;        // no exception was caught, clean the memory

但是如果在最后一个delete之前,有另一个代码可能抛出异常,那么您是对的,并且确实存在导致内存泄漏的可能路径,因为在这种情况下,分配的内存将永远不会被清理。

令人遗憾的是,人们编写的代码没有使用这种语言提供的优秀特性来避免如此丑陋的内存管理。通常,具有自动存储持续时间的对象就足够了,您将发现自己遵循RAII习惯用法,或者在需要动态分配的情况下,将这些裸指针与一些对象包装起来仍然是一个好主意……智能指针很有帮助。