gpt4 book ai didi

c++ - 如果构造函数抛出异常,如何删除对象?

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

所以我们有一个构造函数可以根据传递给它的参数抛出异常,但我们不知道如果发生这种情况如何删除对象。代码的重要部分:

try
{
GameBase *gameptr = GameBase::getGame(argc, argv);
if (gameptr == 0)
{
std::cout << "Correct usage: " << argv[PROGRAM_NAME] << " " << "TicTacToe" << std::endl;
return NO_GAME;
}
else
{
gameptr->play();
}
delete gameptr;
}
catch (error e)
{
if (e == INVALID_DIMENSION)
{
std::cout << "Win condition is larger than the length of the board." << std::endl;
return e;
}
}
catch (...)
{
std::cout << "An exception was caught (probably bad_alloc from new operator)" << std::endl;
return GENERIC_ERROR;
}

在第三行中,GameBase::getGame() 调用从 GameBase 派生的其中一个游戏的构造函数并返回指向该游戏的指针,这些构造函数可以抛出异常。问题是,如果发生这种情况,我们如何才能删除 gameptr 指向的(部分?)对象?如果抛出异常,我们将退出 gameptr 的范围,因为我们离开了 try block 并且无法调用 delete gameptr

最佳答案

要评估异常安全性,您需要在 GameBase::getGame 中提供对象构造的更多详细信息。

规则是,如果构造函数抛出异常,则不会创建对象,因此不会调用析构函数。关联的内存分配也被释放(即对象本身的内存)。

那么问题就变成了,内存是如何分配的?如果它与 new GameBase(...) 一起使用,则无需取消分配或删除结果指针 - 内存由运行时取消分配。


为了清楚地说明已经构造的成员变量会发生什么;它们在“父”对象除外时被破坏。考虑 sample code ;

#include <iostream>
using namespace std;
struct M {
M() { cout << "M ctor" << endl; }
~M() { cout << "M dtor" << endl; }
};
struct C {
M m_;
C() { cout << "C ctor" << endl; throw exception(); }
~C() { cout << "C dtor" << endl; }
};
auto main() -> int {
try {
C c;
}
catch (exception& e) {
cout << e.what() << endl;
}
}

输出为;

M ctor
C ctor
M dtor
std::exception

如果要动态分配M m_ 成员,则优先使用unique_ptrshared_ptr 而非裸指针,并允许智能为您管理对象的指针;如下;

#include <iostream>
#include <memory>
using namespace std;
struct M {
M() { cout << "M ctor" << endl; }
~M() { cout << "M dtor" << endl; }
};
struct C {
unique_ptr<M> m_;
C() : m_(new M()) { cout << "C ctor" << endl; throw exception(); }
~C() { cout << "C dtor" << endl; }
};

这里的输出反射(reflect)了上面的输出。

关于c++ - 如果构造函数抛出异常,如何删除对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36302144/

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