It might work, but as soon as i goes out of scope, you have a dangling pointer.
Printable View
This is how you never repeat data with boost:
Basically, the idea is to create a shared pointer for each individual resource item, use an ID to find the single shared pointer to the data, and instead of duplicating data we create a boost::weak_ptr and return it and boost pretty much handles all the cleanup for you.Code:#ifndef RESOURCE_MANAGER_H
#define RESOURCE_MANAGER_H
#include <vector>
#include <map>
#include <string>
#include <boost\shared_ptr.hpp>
#include <boost\weak_ptr.hpp>
template< typename T_ >
class Resource_Manager
{
public:
typedef T_ value_type; // std library convention
typedef boost::shared_ptr<T_> Resource_Ptr;
typedef boost::weak_ptr<T_> Resource_Observer;
typedef std::map< std::string, Resource_Ptr > Resource_Map;
Resource_Manager<T_>() {};
~Resource_Manager<T_>() {};
Resource_Observer Request_Resource(const std::string & name)
{
Resource_Map::iterator it = mResources.find(name);
if (it == mResources.end())
{
Resource_Ptr Raw_Resource(new T_);
Raw_Resource->Load(name);
mResources.insert(std::make_pair(name, Raw_Resource));
Resource_Observer Resource(Raw_Resource);
return Resource;
}
else
{
return Resource_Observer(it->second);
}
}
void Request_Resource_Removal(const std::string & name)
{
Resource_Map::iterator it = mResources.find(name);
if (it != mResources.end())
{
mResources.erase(it);
}
}
private:
Resource_Map mResources;
};
#endif
Many libraries in boost are in almost standard. AFAIK the ptr containers library is not in the next standard, but it is still widely used and tested because it is a part of boost.
Switching to a ptr_vector is probably a better solution than creating your own version of it.
Another option is to change the class C to make copying less expensive. for example, if you only need to copy the class when it is inside the vector, then you can move its implementation into a single struct that is held via shared_ptr (another boost item that will be in the next standard). That way you don't have to change the syntax of when you use the vector, you only have to change the implementation of the particular class that is currently slow to copy.
Remember, though, that the solution above assumes the class won't break any other code if you switch to a shared implementation copy versus a cloned implementation copy.
Alternatively, if you don't like *(my_vector_of_pointers_to_obgects[i]), you can also do my_vector_of_pointers_to_obgects->at(i).
Looks better too.
Has different behaviour, though - an additional index check, and a throw if the check fails.
Which is a good thing.
If the index doesn't exist and you use [], you get undefined behavior (bad) or crash.
If the index doesn't exist when you use at, you get an exception. You can handle it and your program can correct the error and continue execution. Or you could just not handle the exception and then the program will crash or display a fancy error message and terminate.
In 99.99% of the time, it doesn't matter unless you are writing very time-sensitive code.
GCC has the -D_GLIBCXX_DEBUG flag, which in particular causes [] to do bounds checking - see
http://gcc.gnu.org/onlinedocs/libstdc++/debug.html
so one can do a debug build with bounds checking, then recompile without the flag without changing the source later, which I prefer to using at(), the bounds checking of which can't be turned off. I don't know if other compilers have a similar feature.
Exactly as this book suggests: Use a checked STL implementation