【问题标题】:Am I correct in my assumption about an error on this assignment operator?我对这个赋值运算符错误的假设是否正确?
【发布时间】:2012-12-11 02:19:22
【问题描述】:

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=() throws,bar1bar2 会泄漏。

【问题讨论】:

  • try-catch,这一定是编写异常安全代码的最糟糕方式...
  • 在文章后面作者提供了一个使用 auto_ptr 的解决方案,我认为这是正确的。
  • auto_ptrs?那些已经被弃用的?
  • 我认为 unique_ptr 当时不可用
  • 我想到了复制交换。不过@user1042389、boost::shared_ptr 可能是。

标签: c++ memory-leaks assignment-operator


【解决方案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

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

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

【讨论】:

  • OP指出TSuperFoo::operator=可能会在try-catch之外抛出
  • @K-ballo 抱歉,我没注意到。感谢您指出,我已经编辑了答案,现在应该没问题了:)
猜你喜欢
  • 2014-12-26
  • 1970-01-01
  • 2020-02-09
  • 2017-09-17
  • 2021-08-28
  • 1970-01-01
  • 2013-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多