Try/catch块用于在构造函数内部将简单内存分配到公共原始指针



我有一个原始指针的情况,我不能改变为智能指针,因为它是接口的一部分(我不想破坏使用它的任何代码):

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包围这个吗?为什么?我想听听你的意见。

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

谢谢!

No.

完全没有意义。

int构造可能不会抛出,因此这里唯一可能的异常是std::bad_alloc。你在这案子里干什么?

  • 好吧,首先你在一个NULL指针上做delete,这是一个无操作。分配失败,所以你没有"回收"任何东西。
  • 那么你正在重新抛出异常。

。没有try/catch会发生什么

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

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


同样,不要忘记你的复制构造函数

在这种情况下,没有必要使用try catch,因为如果你在new pointer中得到std::bad_alloc将为NULL,它将导致删除NULL,这将不做任何事情。

只是附加信息

从构造函数抛出异常是一个潜在的坏主意。看看代码
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

因此,新代码不调用析构函数,因为object还没有完全构造。我们有内存泄漏。

你应该怎么做来避免它?

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

最新更新