Re: Useless use of smart pointers
On Jun 4, 7:46 pm, Matthias Kluwe <mkl...@gmail.com> wrote:
Some old code is getting an overhaul at the moment and using smart
pointers is an obvious part of this. Let's look at a simplified
example.
Consider having a type
class Obj;
that is expensively constructed from a file. Once constructed, they
are never modified and used (shared) a zillion times by a few thousand
other objects (think of data or parameter tables). Therefore, these
objects are stored in a std::map by some key (e.g. filename)
encapsulated by some type like this:
class ObjStore1 {
public:
const Obj* get( const std::string& filename );
~ObjStore1();
private:
typedef std::map< std::string, const Obj* > store_type;
store_type store;
};
The get method retrieves some Obj from the map, constructing it on
demand:
const Obj* ObjStore1::get( const std::string& filename ) {
store_type::const_iterator it = store.find( filename );
if ( it != store.end() ) {
return it->second;
} else {
std::auto_ptr< Obj > pObj( new Obj( filename ) );
store[ filename ] = pObj.get();
return pObj.release();
}
}
In this implementation, ~ObjStore1 needs to delete the Objs:
ObjStore1::~ObjStore1() {
store_type::iterator it;
for ( it = store.begin(); it != store.end(); ++it ) {
delete it->second;
}
};
A "simple" modification could be using std::tr1::shared_ptrs in the
map:
class ObjStore2 {
public:
const Obj* get( const std::string& filename );
private:
typedef std::map< std::string,
std::tr1::shared_ptr< const Obj > > store_type;
store_type store;
};
What have we won? There's no destructor needed anymore, and the get
method gets rid of std::auto_ptr:
[]
However, the runtime memory consumption of your new code has
increased. This is because shared_ptr has two pointer members (at
least boost one does). shared_ptr also allocates an object with a
counter behind the scenes, so for every object managed by shared_ptr
you incur +1 memory allocation.
Is this already misuse of std::tr1::shared_ptr? And there are still
many naked pointers thrown around in the code (but clearly documented
as being "weak").
Am I right not to consider to return a std::tr1::weak_ptr from the get
method?
IMO, the original code is good enough for its purpose and introducing
smart pointers does not make it any better. A good design is not when
there is nothing left to add, rather when there is nothing left to
remove.
--
Max
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]