2

Richard Gillam 在他的“赋值运算符的剖析”中,当他在论文的开头说了以下内容时,他可能做出了错误的陈述:

“这个问题的一个正确答案应该是这样的:”

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=()抛出,bar1并且bar2会泄漏。

4

1 回答 1

1

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

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

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

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

于 2012-12-24T19:48:59.890 回答