gpt4 book ai didi

c++ - 我需要手动销毁抛出的物体吗?

转载 作者:行者123 更新时间:2023-11-27 22:32:25 26 4
gpt4 key购买 nike

我只是想知道在 C++ 中是否需要手动销毁抛出的对象?

在下面的代码中,如何销毁抛出的0?

try
{
...
throw 0;
}
catch(int i)
{
// How to destroy the thrown 0?
}

在下面的代码中,如何销毁抛出的CString对象?

try
{
...
throw CString(_T("Hello"));
}
catch(CString& str)
{
// How to destroy the thrown str?
}

在下面的代码中,我可以销毁抛出的对象,因为它是作为 CString* 从堆中分配的

try
{
...
throw new CString(_T("Hello"));
}
catch(CString* lpStr)
{
delete lpStr;
}

最佳答案

您不需要也不允许手动销毁异常对象或 catch 参数。

throw 将从其操作数中复制初始化一个新的未命名对象,异常对象,然后该对象被 catch 捕获堵塞。 Caught 表示 catch block 的参数将从异常对象中初始化。

catch block 退出时,它的参数会自动销毁,如果它没有重新抛出就退出(并且如果没有 std::exception_ptr 引用它),异常对象也将被销毁,就像具有自动存储持续时间的对象在声明它们的 block 退出时被销毁或临时对象在创建它们的完整表达式结束时被销毁一样。

在您的第一个代码示例中,int 类型的异常对象被初始化为值 0 并且您按值捕获它,这意味着您正在创建一个新对象int 类型作为 catch 参数中的变量,从异常对象初始化。当 catch block 退出时 catch 参数中的 int 被销毁,假设你没有重新抛出,异常对象也是销毁。

在您的第二个示例中,CString 类型的异常对象是从 CString(_T("Hello")) 创建的临时对象中初始化的。临时 CString(_T("Hello")) 在异常对象初始化后被销毁,因为这是创建它的完整表达式的结尾。

由于复制省略,临时对象永远不会真正实现,CString 异常对象直接从 _T("Hello") 初始化。 (这是强制性的,因为 C++17 之前是允许的。)

您通过引用捕获异常对象,这意味着不会创建新拷贝并且 str 将引用异常对象。当离开 catch block 而不重新抛出时,异常对象将再次自动销毁。

在第三个示例中,您将抛出一个 CString* 并按值捕获它,因此适用与示例 1 中相同的注意事项。当离开 catch block 而不重新抛出时,指针 lpStr 和异常对象(也是一个 CString*)将被销毁。

然而,销毁指针并不意味着指针指向的对象被销毁。 (这就是为什么不应将原始指针用作拥有指针的原因。)

因此,由于指针指向使用 new 创建的对象,如果您不想,确实需要通过调用 delete lpStr; 来销毁该对象newed CString 泄漏。但是,此删除 不会删除异常对象或catch 参数delete 销毁给它的指针指向的对象。 catch 参数是指针lpStr 本身,一个不能被deleted 的自动存储持续时间变量。异常对象是另一个指针(具有相同的值)并且未命名,没有任何可能的方式在您的示例中引用它。

您应该像在第二个示例中那样更喜欢通过引用捕获,并且您应该避免将 new 用于任何真正的事情。有智能指针 std::unique_ptrstd::shared_ptr 用于具有正确所有权语义的自由存储分配。

关于c++ - 我需要手动销毁抛出的物体吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59318149/

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