1

我有一个原始指针的案例,我无法将其更改为智能指针,因为它是接口的一部分(并且我不想使用它破坏任何代码):

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

  int * m_pStuff; // public!
};

我不想在我的ctor中做太多事情。就像:

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 包围它吗?为什么?我想听听你对此的看法。

另外,除了分配时内存不足之外,您是否看到任何异常的可能性?在那种情况下,已经分配的内存会被自动回收,对吧?

谢谢!

4

3 回答 3

5

不。

这是完全没有意义的。

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

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

即正是没有try/会发生什么catch

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

不过,此建议不一定适用于其他类型。


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

于 2013-04-16T13:32:40.337 回答
0

在这种情况下,不需要 try catch,因为如果你在 new 指针中得到 std::bad_alloc 将是 NULL 并且它会导致 delete NULL 什么都不做。

于 2013-04-16T13:33:05.433 回答
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;
    }
}

此代码按预期工作:

~Foo()
捕获:std::bad_alloc

但是如果我们注释Foo(nullptr, nullptr)行和取消注释// _a(nullptr), _b(nullptr)行,我们会看到这个输出:

捕获:std::bad_alloc

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

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

  • 不要使用原始指针,使用智能指针代替它。
  • 将一个构造函数封装到另一个构造函数中,就像在第一个示例中一样。
于 2013-04-16T14:01:27.303 回答