gpt4 book ai didi

c++ - 动态内存和构造函数异常

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:09:01 24 4
gpt4 key购买 nike

今天早些时候,我发现了函数 try-catch block (实际上来自 here),然后进行了一些研究 - 显然它们的主要用途是捕获构造函数初始化列表抛出的异常。

无论如何,这让我想到了失败的构造函数,我已经到了一个只需要一点澄清的阶段。这只是我想了解更多有关该语言的内容,所以我没有实际示例,但是这里...


鉴于此示例代码:

class A
{
private:
B b
C *c; //classes B, C & D omitted for brevity as not really relevant
D d;
public
A(int x, int y, int z)
};

A::A(int x, int y, int z)
try
: b( x )
, c( new C(y) )
, d( z )
{
//omitted
}
catch(...)
{
//omitted
}

在这些情况下会发生什么:

  1. b 的初始化抛出异常。
  2. c 的初始化抛出异常。
  3. d 的初始化抛出异常。

具体来说,我至少想知道:

  • 什么会/可能会导致 new C(y) 内存泄漏。 我想只有 3 个? (参见 here)
  • 你可以在 catch 中删除 b 吗? 情况 1 和情况 2 是否危险?

显然,我想最安全的做法是使 c 成为智能指针。但暂时忽略该选项,最好的行动方案是什么?

在初始化程序中将 c 设置为 NULL,然后在构造函数主体中调用 new 是否安全?

那就意味着 delete c 必须放在 catch 中,以防在构造函数主体中抛出其他东西?这样做是否存在安全问题(即,如果是 c = new C(y); 本身抛出)?

最佳答案

Try/catch 函数 block 不受欢迎,就像 goto 一样——可能存在一些它们有意义的极端情况,但最好避免它们:当一个对象无法构造时,你能做的最好的事情失败并且快速失败。

关于您的具体问题,当在构造函数中抛出异常时,所有完全构造的子对象都将被销毁。这意味着在 b 的情况下它将被销毁,在 c 的情况下,它是一个原始指针,什么都不做。最简单的解决方案是将 c 更改为处理分配内存的智能指针。这样,如果 d 抛出异常,智能指针将被销毁并释放对象。这与 try/catch block 无关,而是与构造函数的工作方式有关。

一般来说,从 catch block 中删除指针也是不安全的,因为在执行初始化之前无法保证指针的实际值。也就是说,如果 bc 抛出,则 c 可能不是 0,但也不是有效指针,并且删除它将是未定义的行为。总是有一些情况,就好像你可以保证 bc 都不会抛出,并假设 bad_alloc 不是你的东西通常从中恢复过来,那么它可能是安全的。

注意,如果由于某些特定原因需要用原始指针保留一个指针,最好在初始化列表中将其初始化为0,然后在构造 block 内部创建对象,以避免出现此问题。还请记住,直接在一个类中持有多个(原始)资源使得很难确保没有资源泄漏——如果第一个资源被创建和分配,而第二个资源失败,析构函数将不会被调用并且资源会泄漏。同样,如果您可以使用智能指针,您需要处理的问题就会少一些。

关于c++ - 动态内存和构造函数异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3181040/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com