简体   繁体   中英

auto_ptr and containers - C++

I'm currently working on a 2D game engine and I've read about auto_ptr's and how you should never put them in standard containers.

My engine has this structure:

StateManager -- has many --> State's.

States are created and allocated in main, outside of the engine. I want the engine to store a list/vector of all the states so I can change between them on command.

For example:


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

Since states die when and only when the application dies, can I use this approach?


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); }

The StateManager should only maintain a vector of pointers to the states, it shouldn't need to take ownership. When I want to change state in the engine, I just change the activeState pointer to point to the desired state which is found in the stateList vector.

Is this a bad approach?

Why not use std::vector<State> instead and not worry about storing pointers? It sounds like the list of states is fixed so any iterators will not be invalidated during the lifetime of the program.

Alternatively, I've found the Boost Pointer Container library to be useful for this sort of thing.

Since StateManager doesn't own contained objects, its contained type should be State*, and not smart pointer. It's OK to use auto_ptr in the main function, this is not related to the StateManager container.

In the case you want to have container which is responsible for contained objects lifetime, you can use smart pointer as contained type. But using auto_ptr is dangerous for this, since it has primitive ownership algorithm. It is better to use shared_ptr in such containers.

If there is nothing that precludes it (polymorphism etc.), then I'd just use the simplest approach, namely std::vector<State> . activeState can still be a pointer (or an iterator).

The way you use auto_ptr in the code you posted is not going to work.

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

When the "test" variable goes out of scope, its' destructor will be called which will delete the SomeState object you just registered with StateManager. So now your StateManager is keeping a pointer to a deleted object, which will probably lead to a crash down the way.

Instead, you could look into using a reference counter smart pointer type, eg boost::shared_ptr .

auto_ptr s are supposed to manage the object's life time within a specified context. eg

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

// do something delete pNewObject; }

In the above function, if some exception occurred in //Do Something code, the object will not be free d and you will face memory leak in the code. We use Auto_ptrs in this kind of situations.

But it's not suitable for the following context (releasing an array). In the destructor of auto_ptr, it calls delete ptr; but with arrays we have to call delete[] ptr; If you use auto_ptr with array, memory leak will be occurred and leads to unexpected behavior void foo() {

unsigned char* pStream = new unsigned char[size]; ....

delete[] pStream; }

If you don't have much state and it's not so greedy for memory I recommend to use Singleton objects for your state classes. So you don't have to worry about memory management. State manager can handle the active state and the state objects but I don't think it's a good idea to Initialize the state object outside state manager and do the rest in statemanager and somewhere else. please ensure that the creation and destruction are unified

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM