C++-正确的抛出和捕获异常方式

8

可能是重复问题:
在堆栈上抛出对象异常,使用new会导致内存泄漏吗?

在C++中,你是使用new运算符还是不使用来抛出异常呢?因为这两种方式都可以抛出异常。

void KillUnicorns()
{
    throw IllegalActionException();
}

int main()
{
    try
    {
        KillUnicorns();
    }
    catch (IllegalActionException e)
    {
         // Handle exception
    }
    return 0;
}

尽管下面的示例会泄漏内存?
void KillUnicorns()
{
    throw new IllegalActionException();
}

int main()
{
    try
    {
        KillUnicorns();
    }
    catch (IllegalActionException* e)
    {
         // Handle exception
    }
    return 0;
}

什么是在C++中抛出异常的正确方式?
2个回答

9

我可以不使用 new 抛出异常:

void KillUnicorns()
{
    throw IllegalActionException();
}

我会使用const引用来捕获它,代码如下:

catch (const IllegalActionException & e)
{   // ^^^^ note const             ^^ note reference!

}

它避免了复制。它避免了使用new,因此使您免于使用delete

1
有一个快速的问题。const IllegalActionException &eIllegalActionException const& e 能够达到相同的结果吗?就像 @Martin 的评论中所看到的那样。 - Kevin
2
@ Kevin:在类型前缀或后缀常量是一种风格问题(你可以看到两者都有)。结果是相同的。 - Martin York

8

从技术上讲,你可以两种方式都做。

但更传统的方式是抛出对象:
还请注意使用const引用捕获(这可以防止异常切片)

try
{
    KillUnicorns();
}
catch (IllegalActionException const& e)
{                         // ^^^^^^^^
     // Handle exception
}

5
补充一下,通常会为异常对象保留内存。如果您进行动态分配,那么您将使用该内存来存储指针,但仍然尝试进行标准的动态分配(在“堆”上,如果您的实现使用其中一个)。如果异常的原因是您的内存不足,这不太好。当然,您还会为自己在稍后释放该内存方面制造麻烦。 - Lightness Races in Orbit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接