删除“this”指针后阻止对象使用

坦率

我正在处理具有以下问题的应用程序。基本上有很多对象可能会隐式地销毁自己。

void Foo::func()
{
    ...
    Bar b;
    b.func2();
}

这里func2可能会破坏foo调用它对象。由于这不是很明显,我想确保foo在此调用之后不能访问对象的任何成员变量,因为我不能保证它们仍然有效。如果这个对 b 的调用是最后一个调用,我完全没问题,但由于我不是唯一一个在这个项目上工作的人,而且破坏并不明显,我想this在这些调用之后实现一些阻止使用的东西有没有办法在不完全重构当前设计的情况下实现这一点(因为它在整个项目中被广泛使用)?

一些背景资料:

它是一个 Qt UI 应用程序,它使用 QML 来跟踪一堆“屏幕”(一个屏幕是一个 QML + 其对应的 C++ 模型)。Bar我的示例中类是控制屏幕生命周期的“堆栈管理器”。这是一个单身人士(我知道)。Foo类为特定QML一个C ++模型。该函数Foo::func()是可以从 QML 中的用户输入或其他系统事件调用的函数。该函数通常处理事件,但有时它可以告诉屏幕管理器删除一个或多个屏幕,这反过来又删除与该屏幕对应的模型(可能是调用模型)。

克里斯托夫

严重的设计问题?

this指针不能被阻止。与所有原始指针一样,在取消引用它之前,您必须确保它是有效的。

但这还不是全部:如果Foo调用的fun2()是自动存储持续时间的本地对象怎么办?

  • 如果您通过调用其析构函数来销毁函数调用中的对象,则必须确保在同一位置仍然存在有效对象:否则在离开定义对象的块时自动调用析构函数可能会导致未定义的行为。
  • 如果你想要delete对象而不是仅仅销毁它,那么无论如何它都将是未定义的行为

带有智能指针的替代设计

摆脱这种情况的一种方法是使用工厂创建所有FooBar对象(确保构造函数不是公共的),并让这些工厂返回shared_ptr

这样做的好处是,如果一个对象不再使用,它​​会自行销毁。这比手动管理销毁要干净得多。

然而,您将面临几个挑战:

  • 您必须重构所有代码以用智能指针替换原始指针
  • 为了避免由于交叉引用(两个对象各自保持一个指向另一个的 slart 指针)而导致无休止的生存,您需要弄清楚何时使用shared_ptr(如果指针必须确保对象仍然存在)以及何时使用weak_ptr(即无助于使对象保持活动状态的指针)。

带有状态的替代设计

另一种选择是使用状态来区分可以使用的活动对象和不再使用的已故对象。因此,与其删除对象,不如调用一个状态更改函数来清理/重置对象。

这可以实现:

  • 要么非常适合状态设计模式(但这可能需要一些广泛的重构),
  • 或者用一个简单的标志。然后将在每个成员函数的开头以及在访问可能会更改对象状态的调用之后的数据成员之前检查它。这仍然容易出错并需要分析,但主要需要“本地”更改,因此为重构提供了更大的灵活性。

这种方法的优点是状态更改函数将非常简单(您当前在析构函数中拥有的大部分内容,但避免它们可能第二次意外完成)并使棘手的部分非常明显。

难点在于确保死者的物品得到彻底清洁。因此,您需要解决前面已经提到的所有权问题,并确保对象不会在其操作过程中被删除。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章