On May 9, 10:50 am, wiskey5alpha <wiskey5Al...@gmail.comwrote:
Hello all.
I have a design question.
assuming we have
class Bar {...} // body omitted for clarity
class Foo
{
// should Bar be implemented as a pointer or not here ?
Bar *m_bar; // OPTION 1
// or
Bar m_bar; // OPTION 2
... // body omitted for clarity
Foo::Foo()
// OPTION 1
m_bar = new Bar;
m_bar.setID(1);
// or
m_bar.setID(1);
I have seen both of these methods used, so I am wondering if there
is any memory or speed differences between the two ?
To add to the other comments, you should use initializer lists rather
than the constructor body (
http://www.parashift.com/c++-faq-lite/
ctors.html#faq-10.6), and prefer to use the constructor parameters to
initialize member variables and set class invariants rather than
manual setting things up as you do with Bar::setID(), which could
allow internally invalid objects to hang around and cause trouble.
(Consider also the named parameter idiom,
http://www.parashift.com/c++-faq-lit...tml#faq-10.18).
Also, to prevent memory leaks, you should generally use smart pointers
(cf.
http://www.parashift.com/c++-faq-lit...html#faq-16.22
and the following FAQs) and RAII containers like std::vector (http://
http://www.parashift.com/c++-faq-lit....html#faq-34.1) rather than
raw pointers. In the first place, with smart pointers you needn't
destroy the created objects explicitly in your destructor, and in the
second place, you gain exception safety in your constructors (cf.
http://www.parashift.com/c++-faq-lit....html#faq-17.2) and
elsewhere. Consider:
class Foo
{
Bar *m_bar1;
Bar *m_bar2;
public:
Foo()
: m_bar1( new Bar( 1 ) )
, m_bar2( new Bar( 2 ) )
{}
~Foo()
{
delete m_bar2;
delete m_bar1;
}
// ...
};
If the construction of Foo::m_bar2 throws an exception (out of memory,
invalid parameter, whatever), then the memory from m_bar1 is leaked
since the destructor is not called unless the constructor completed
successfully. Probably better is to change the member variable types
from Bar* to std::tr1::shared_ptr<Bar(aka, boost::shared_ptr<Barif
your standard C++ library doesn't have TR1 yet) or similar. Then you
can drop the destructor altogether and you have exception safety in
your constructor (cf. the Law of the Big Two,
http://www.artima.com/cppsource/bigtwoP.html),
but the rest of your code remains unchanged and happily oblivious that
it is now smarter.
One of your goals should be to write code that is easy to use
correctly and hard to use incorrectly, and another should be to let
the compiler do the work of releasing resources like memory, files,
and locks for you rather than doing it explicitly (Sutter and
Alexandrescu, _C++ Coding Standards_, Item 13 and
http://www.research.att.com/~bs/bs_faq2.html#finally).
Cheers! --M