2

我是一个爱好 c++ 程序员,这是我的第一篇文章。

首先,让我告诉你,我正在开发跨平台的 ansi C++。

我刚刚做了很多工作来弄清楚内存管理,我终于掌握了使用 std::vector 并在删除期间手动管理指针的窍门。

另外,我一直在使用 boost::smart_ptr ,它终于点击了。

但是我刚刚遇到了一些代码,其中我们将有一个类 Foo,它的构造函数向 FooManager (单例)注册自己

Foo::Foo()
{
 FooManager::Instance()->register(this);
}

在 FooManager 的销毁过程中,它遍历 std::vector 并对每个元素应用擦除和删除,有效地清理了 Foo 的内存。

FooManager::~FooManager()
{
    // iterate over the container of Foo pointers
    // erase the pointer from container and delete the pointer
}

我很困惑,因为我们不是 a) 在创建过程中使用 boost::smart_ptr 来包装指针,并且 b) 我们在构造函数和析构函数中使用内存管理技巧。

这是一个可行的解决方案,还是使用单例的析构函数来清理它管理的对象是否存在可怕的危险?

从我自己的测试中,我发现了一个根本性的缺陷。Foo 不应再在堆栈上分配。当对象超出范围时,它会取消引用自身。当调用 FooManager 的析构函数时,它会尝试再次删除它。这会产生一个断言错误:

_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));

这是唯一的缺点吗?我应该在 Foo 构造函数之外向管理器移动注册吗?我是否应该有一个 FooManager 的单独功能来清除我在程序生命周期结束时手动调用的内存?您对此事有何看法?

4

2 回答 2

0

切线,我认为你的类的设计有点不对称:

  1. 所有 Foo 对象在创建时注册自己;
  2. FooManager 删除所有注册在删除时删除所有已注册的 Foo 对象。

问题是: FooManager 只是聚合 Foo 对象还是也在处理它们的生命周期?

  • 如果 FooManager 只是为 Foo 对象提供聚合,那么它在销毁时不应该删除它们,因为它不“拥有”它们;一个简单的内部注销就足够了(注意:多线程程序中可能存在问题)。

  • 如果 FooManager 应该对 Foo 对象有更严格的控制(即处理它们的整个生命周期),工厂模式可能更合适:只有 FooManager 可以分配 Foo 对象。

于 2012-12-28T22:51:05.087 回答
0

我看到几个问题:

  1. FooMananger 的单例实例是一个静态变量,具有从程序开始到结束的生命周期。如果我们只在 FooManager 的析构函数中删除 Foo,它可能只在程序结束时被调用,那么我们根本没有做任何内存管理。它相当于永远不会删除任何 Foo 实例。不是吗?

  2. 正如您已经发现的那样,FooManager 在 Foo 的构造函数中注册指针的方式使得无法在堆栈上分配 Foo 对象。你最终会得到一个指向无效内存位置的指针,或者你不应该触摸的地方。

通常的做法是使用智能指针,取决于你的需要,你可以使用 boost::shared_ptr,或者 boost::scoped_ptr、std::uniqe_ptr (c++11) 等。

于 2012-12-28T22:35:01.360 回答