3

我目前正在研究一个 2D 游戏引擎,并且我已经阅读了有关 auto_ptr 以及如何永远不要将它们放入标准容器中的信息。

我的引擎有这样的结构:

StateManager -- 有很多 --> 状态的。

状态是在引擎之外的 main 中创建和分配的。我希望引擎存储所有状态的列表/向量,以便我可以根据命令在它们之间进行更改。

例如:

SomeState *test = new SomeState();
StateManager->registerState(test);

由于状态仅在应用程序死亡时死亡,我可以使用这种方法吗?

std::auto_ptr<SomeState> test(new SomeState());
StateManager->registerState(test.get());

// Inside StateManager State *activeState; // State manager then maintains a vector std::vector<State*> stateList; // and upon registerState it adds the pointer to the vector void registerState(State *state) { stateList.push_back(test); }

StateManager 应该只维护一个指向状态的指针向量,它不需要拥有所有权。当我想更改引擎中的状态时,我只需更改 activeState 指针以指向在 stateList 向量中找到的所需状态。

这是一个不好的方法吗?

4

5 回答 5

9

为什么不使用 std::vector<State> 而不用担心存储指针?听起来状态列表是固定的,因此在程序的生命周期内任何迭代器都不会失效。

或者,我发现Boost Pointer Container库对这类事情很有用。

于 2010-07-13T11:48:44.587 回答
4

由于 StateManager 不拥有包含的对象,因此其包含的类型应该是 State*,而不是智能指针。在 main 函数中使用 auto_ptr 就可以了,这个和 StateManager 容器无关。

如果您想要拥有负责包含对象生命周期的容器,您可以使用智能指针作为包含类型。但是使用 auto_ptr 是危险的,因为它有原始的所有权算法。最好在这样的容器中使用 shared_ptr。

于 2010-07-13T11:52:03.860 回答
3

如果没有什么可以排除它(多态性等),那么我只会使用最简单的方法,即std::vector<State>. activeState仍然可以是指针(或迭代器)。

于 2010-07-13T11:47:06.023 回答
1

您在发布的代码中使用 auto_ptr 的方式行不通。

std::auto_ptr<SomeState> test(new SomeState());
StateManager->registerState(test.get());

当“test”变量超出范围时,将调用它的析构函数,这将删除您刚刚在 StateManager 中注册的 SomeState 对象。因此,现在您的 StateManager 保留了一个指向已删除对象的指针,这可能会导致崩溃。

相反,您可以考虑使用引用计数器智能指针类型,例如boost::shared_ptr

于 2010-07-13T11:53:03.027 回答
0

auto_ptr 应该在指定的上下文中管理对象的生命周期。例如

void foo() { MyObject* pNewObject = new MyObejct;

// 做点什么 delete pNewObject; }

在上面的函数中,如果在 //Do Something 代码中发生了一些异常,对象将不会是 free d 并且您将面临代码中的内存泄漏。我们在这种情况下使用 Auto_ptrs。

但它不适合以下上下文(释放数组)。在auto_ptr的析构函数中,调用delete ptr;但是对于数组,我们必须调用 delete[] ptr; 如果将 auto_ptr 与数组一起使用,则会发生内存泄漏并导致意外行为 void foo() {

无符号字符* pStream = 新无符号字符[大小];……

删除[] pStream; }

如果您没有太多状态并且对内存不是那么贪婪,我建议您将 Singleton 对象用于您的状态类。所以你不必担心内存管理。状态管理器可以处理活动状态和状态对象,但我认为在状态管理器之外初始化状态对象并在状态管理器和其他地方完成其余工作并不是一个好主意。请确保创建和销毁是统一的

于 2010-07-13T12:30:03.360 回答