在内部构造函数中,使用/ catch块将简单的内存分配到公共​​原始指针中?

时间:2013-04-16 13:30:55

标签: c++ exception pointers constructor dynamic-memory-allocation

我有一个带有原始指针的情况,我无法更改为智能指针,因为它是界面的一部分(我不想破坏使用它的任何代码):

struct Foo
{
  Foo();
  ~Foo();

  int * m_pStuff; // public!
};

我不想在我的病人身上做太多事情。就像这样:

m_pStuff = new int[dynamically_obtained_size_which_is_greater_than_0];
m_pStuff[0] = 0;

然后在析构函数中删除它。

现在,我想知道使用try / catch是否值得围绕它:

Foo::Foo()
  : m_pStuff(0)
{
  try
  {
    m_pStuff = new int[dynamically_obtained_size_which_is_greater_than_0];
    m_pStuff[0] = 0;
  } 
  catch(...)
  {
    delete m_pStuff;
    throw;
  }
}

我可以看到的观点:

  • 更复杂的代码
  • 并不是真的希望在那里发生任何异常(除非分配时空间不足)
  • 并不是真的希望代码能够改变

我可以看到的要点:

  • 向潜在的未来编码员表明,他们应该小心处理任何抛出异常并将其放入已经存在的try块中
  • 如果发生任何异常,则会解决内存释放问题

我还是犹豫不决:我是否应该尝试使用try / catch?为什么?我想就此发表意见。

此外,您是否看到在分配时由于内存不足而导致异常的可能性?在这种情况下,已经分配的内存将被自动回收,对吧?

谢谢!

3 个答案:

答案 0 :(得分:5)

没有

这完全没有意义。

int构造可能不会抛出,因此这里唯一可能的例外是std::bad_alloc。在这种情况下你在做什么?

  • 好吧,首先你在NULL指针上做delete,这是一个无操作。分配失败,所以你不是“回收”任何东西。
  • 然后你重新抛出异常。

即。确切地说,没有try / catch会发生什么。

只是让异常传播,并记录它是可能的。

但这个建议并不一定适用于其他类型。


另外,请不要忘记您的复制构造函数。

答案 1 :(得分:0)

在这种情况下,try catch中没有必要,因为如果你在新指针中得到std :: bad_alloc将是NULL并且它将导致删除NULL,它将什么都不做。

答案 2 :(得分:0)

只是附加信息

从构造函数中抛出异常是一个潜在的坏主意。看一下代码

class Foo
{
    Foo(int* a, int* b): _a(a), _b(b)
    {

    }

public:
    Foo() :
        Foo(nullptr, nullptr)
        // _a(nullptr), _b(nullptr)
    {
        _a = new int[10];
        _b = new int[100500 * 100500]; // should throw an exception
    }

    ~Foo()
    {
        delete[] _a;
        delete[] _b;

        std::cout << "~Foo()" << std::endl;
    }

private:
    int* _a;
    int* _b;
};

int main()
{
    try
    {
        Foo f;
    }
    catch(std::exception& e)
    {
        std::cout << "Catched: " << e.what() << std::endl;
    }
}

此代码按预期工作:

  

〜富()
  Catched:std :: bad_alloc

但如果我们评论Foo(nullptr, nullptr)行并取消注释// _a(nullptr), _b(nullptr)行,我们会看到此输出:

  

Catched:std :: bad_alloc

因此,新代码不会调用析构函数,因为对象未完全构造。我们有内存泄漏。

你应该怎么做才能避免它?

  • 不要使用原始指针,而是使用智能指针。
  • 将一个构造函数封装到另一个构造函数中,就像在第一个示例中一样。