我有一个原始指针的情况,我不能改变为智能指针,因为它是接口的一部分(我不想破坏使用它的任何代码):
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)
行,我们将看到这样的输出:
因此,新代码不调用析构函数,因为object还没有完全构造。我们有内存泄漏。弹出框:std:: bad_alloc
你应该怎么做来避免它?
- 不要使用原始指针,使用智能指针代替。
- 将一个构造函数封装到另一个构造函数中,就像第一个例子一样。