我目前正在研究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向量中的所需状态。
这是一种不好的方法吗?
答案 0 :(得分:9)
为什么不使用std :: vector&lt; State&gt;而不是担心存储指针?听起来状态列表是固定的,因此在程序的生命周期内任何迭代器都不会失效。
或者,我发现Boost Pointer Container库对这类事情很有用。
答案 1 :(得分:4)
由于StateManager不拥有包含的对象,因此其包含的类型应为State *,而不是智能指针。在main函数中使用auto_ptr是可以的,这与StateManager容器无关。
如果您希望拥有负责包含对象生命周期的容器,则可以将智能指针用作包含类型。但是使用auto_ptr对此很危险,因为它具有原始所有权算法。最好在这样的容器中使用shared_ptr。
答案 2 :(得分:3)
如果没有任何事情可以排除它(多态性等),那么我只使用最简单的方法,即std::vector<State>
。 activeState
仍然可以是指针(或迭代器)。
答案 3 :(得分:1)
您在发布的代码中使用auto_ptr的方式不起作用。
std::auto_ptr<SomeState> test(new SomeState());
StateManager->registerState(test.get());
当“test”变量超出范围时,将调用其析构函数,它将删除刚刚使用StateManager注册的SomeState对象。所以现在你的StateManager保留了一个指向已删除对象的指针,这可能会导致崩溃。
相反,您可以考虑使用引用计数器智能指针类型,例如, boost::shared_ptr
答案 4 :(得分:0)
auto_ptr应该在指定的上下文中管理对象的生命周期。例如
void foo() { MyObject * pNewObject = new MyObejct;
//做点什么 delete pNewObject; }
在上面的函数中,如果在// Do Something代码中发生了一些异常,则该对象将不会自由d并且您将在代码中面临内存泄漏。我们在这种情况下使用Auto_ptrs。
但它不适合以下上下文(释放数组)。在auto_ptr的析构函数中,它调用delete ptr;但是对于数组,我们必须调用delete [] ptr;如果将auto_ptr与数组一起使用,则会发生内存泄漏并导致意外行为 void foo() {
unsigned char * pStream = new unsigned char [size]; ....
delete [] pStream; }
如果你没有太多的状态,并且内存不那么贪心,我建议你使用Singleton对象作为你的状态类。所以你不必担心内存管理。状态管理器可以处理活动状态和状态对象,但我认为在状态管理器外部初始化状态对象并在状态管理器和其他地方执行其余操作并不是一个好主意。请确保创建和销毁统一