如何删除部分类?

How to delete part of a class?

本文关键字:分类 删除 何删除      更新时间:2023-10-16

问题很简单。我有一个可以构造如下的类:

class MyClass {
struct A {
// ...
};
struct B {
// ...
};
};

问题是:MyClass::B中的信息在经过一段时间的预计算后是无用的,而MyClass::A永远不能被删除(程序可能运行了几天(。MyClass::B包含相当多的信息。我想摆脱MyClass::B,同时MyClass::A保持在同一记忆位置。

是否可以在不修改太多数据结构并且不必向MyClass::A添加任何其他内容(特别是指向MyClass::B的指针(的情况下执行此操作?如果是这样,实施它的正确方法是什么?考虑到程序必须尽可能节省内存(让我们将其发挥到极致(。我使用 C++14 顺便说一句。

(还有一个额外的问题:是否可以从MyClass中删除与MyClass::B对应的块?

首先,或者全部是一个类声明。不能删除类声明的一部分。你可能还有这样的东西:

// The exact place of the declaration doesn't matter actually
class A {...}; 
class B {...};
class C {
A a;
B b;
}; 

只需将其更改为使用指针(在当今时代,智能指针,如 std::unique_ptr(:

class C {
A a;
std::unique_ptr<B> b;
void FinishTaskThatRequiredB() {
b.reset(); // calls B::~B() and frees the memory.
}
}; 

好吧,让我们详细说明一下我写的内容:">要么B的生命与MyClass的生命联系在一起,要么它是独立的。在后一种情况下,您必须以某种方式跟踪它"。

把上下文从问题中放回去:

  • MyClass::B 经过一段时间的预计算后毫无用处。
  • 我的类::A 绝不能被删除。

因此,您希望以某种方式跟踪它。如何?嗯,这取决于寿命的规则。

  • 如果B有时可以存在,有时不依赖于难以控制(或完全不可知(的情况,那么有一个指向它的指针,在它无用时设置为nullptr,并在有用时动态分配几乎是唯一的解决方案。

但在这里我们有更多的知识:B首先存在,然后变得无用,并且永远如此。换句话说,在用于创建 A 的一些初始构建步骤之后,您不需要 B。

有一种模式正是这样做的:构建器模式。它的目的是封装一个复杂的构建操作,也许会跟踪一些状态,直到它构建了一些对象,此时它变得无用并且可以被销毁。

class ABuilder
{
public:
setSomeInfo(int);
doSomeComputation(......);
// etc
A get();    /// finalize building of A
private:
int someInfo_ = 0;
};
// somewhere else
auto b = ABuilder();
b.setSomeInfo(42);
b.doSomeComputation(......);
auto a = b.get();
// b is no longer used past that point
// delete it if it was allocated dynamically
// or let it go out of scope if it was automatic

从您的示例中,它会像这样映射:

  • A仍然A.
  • BABuilder.
  • 不需要MyClass

如果您提供了实际的类名和用途,则更容易使示例有意义;)

无论如何,指针很可能是实现您欲望的关键。无论如何,您也需要BMyClass分开。您可以避免在MyClass中使用指针(请参阅问题和其他答案的注释(,如果您单独存储B并反转指针的方向:

class MyClass
{
struct A { };
A a;
};
class Wrapper
{
struct B { };
MyClass* mc;
B b;
};

现在在初始化期间,您将为每个MyClass创建一个Wrapper,很可能包含在两个不同的数组中:

MyClass items[NUMBER_OF_ITEMS]; // global array?
Wrapper* wrappers = new Wrapper[NUMBER_OF_ITEMS];
// assign each item to its corresponding wrapper
// use the wrappers for initialisation
delete[] wrappers;

现在剩下的只是一个指针,如果它是单独初始化例程中的局部变量,你甚至可能会摆脱它......