为什么不可能破坏一个对象,然后用相同的名称再次实例化它

Why is not possible to destruct an object and then instantiate it again with the same name

本文关键字:实例化 不可能 一个对象 然后 为什么      更新时间:2024-04-27

我正在为其他人编写的代码创建单元测试,这些代码不能修改。

我试图销毁一个对象,然后从一开始实例化它(所以构造函数将其置于初始条件(

这是我的代码:

state::State_Machine state_machine_test_off; 
//Check that OFF is initial state
EXPECT_EQ(States::OFF,state_machine_test_off.get_state());
//Change and check the behaviour from OFF to the other States
state_machine_test_off.change_state(States::LOADED);
EXPECT_EQ(States::LOADED,state_machine_test_off.get_state());
state_machine_test_off.~State_Machine(); //Destructor to iniciate again the process
state::State_Machine state_machine_test_off;
state_machine_test_off.change_state(States::INITIALISED);
EXPECT_NE(States::INITIALISED,state_machine_test_off.get_state());
state_machine_test_off.~State_Machine(); //Destructor to iniciate again the process

然后继续。我不想实例化一个新对象的原因是,我有一个很大的状态矩阵,每个状态都可以通过change_state((移动到一些对象,但不能移动到其他对象。

我在互联网上看过关于析构函数的内容,我读到它们可以被显式调用,即使这不是一个很好的实践。

也许有人能告诉我为什么当我销毁并再次实例化对象时编译器会失败

PD:析构函数是默认的析构函数

state::State_Machine::~State_Machine() {}

问题是您正在重新定义已经定义的变量。当你做

state::State_Machine state_machine_test_off; 

您基本上将名称state_machine_test_off锁定在该变量的作用域中。您以后不能执行state::State_Machine state_machine_test_off;来重置它,因为它试图定义一个新变量,并且名称state_machine_test_off已经被采用。

要在销毁对象后重新构建它,需要使用placementnew让它再次调用该对象的构造函数。看起来像

new (&state_machine_test_off) state::State_Machine();

现在在state_machine_test_off的存储器中有一个新的默认构造的state::State_Machine


也就是说,如果你只是将对象重新分配给一个默认的构造值,比如,那么所有这些手动调用和未定义行为的机会都会消失

state_machine_test_off = state::State_Machine{};

不能在调用析构函数后的eve之后,在同一级别的作用域中声明另一个同名变量。析构函数不会从作用域中删除旧名称。

为了解决您的问题,我建议添加新的范围级别,因为在任何给定的时间,您似乎只对几行使用state::State_Machine

{ state::State_Machine state_machine_test_off;
state_machine_test_off.change_state(States::LOADED);
EXPECT_EQ(States::LOADED,state_machine_test_off.get_state()); }
{  state::State_Machine state_machine_test_off;
state_machine_test_off.change_state(States::INITIALISED);
EXPECT_NE(States::INITIALISED,state_machine_test_off.get_state()); }

如果你仍然想显式调用析构函数,你必须确保在同一个对象上多次调用析构因子是安全的(你说过你不能修改现有的代码,所以这要么有效,要么无效(。在实践中,如果这能很好地工作,我会感到惊讶,因为大多数析构函数都假设对象将被销毁,并且不会花时间将其标记为已销毁(这可能需要额外的状态,并且肯定需要周期(。

如果你仍然下定决心,尽管有复杂性和风险,你可以写这样的东西:

state_machine_test_off.~State_Machine(); //Destructor to iniciate again the process
new (&state_machine_test_off) state::State_Machine;

这利用了放置new,如果您只是正确地使用scope,这是完全不必要的(见上文(。您还必须考虑如果构造函数失败会发生什么,特别是因为仍然需要处理已经构造好的对象,并再次调用其析构函数。