private member variables

W

wiskey5alpha

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 ?
 
J

James Kanze

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

It depends somewhat on Bar, and what you're doing with it. In
general, use a value if you can, a pointer if you have to.
... // body omitted for clarity
Foo::Foo()
// OPTION 1
m_bar = new Bar;
m_bar.setID(1);

That would be 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 ?

Probably not enough to worry about. On the other hand, using a
member object is a lot surer and more reliable.
 
3

3DCoderGuy

wiskey5alpha said:
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 ?

I don't think you will see any significant change in memory or speed.



But the reasons why you use an instance of the object or a pointer to the
object would be many.

When you use an instance, the object is instantiated when the class Foo is
instantiated and destroyed when Foo is. But you have to declare the class
Bar for class Foo to us it. On a small class design that might not be a
problem. On large projects the dependency between headers could be
overwhelming.

When you us a pointer to the object you need to instantiate and destroy the
object yourself. But you don't have to declare the full class. E.g.



In Bar.h

class bar

{

.

}



In Foo.h

class bar; //A change to Bar doesn't cause everything that includes
Foo.h to recompile



class Foo

{

Bar *m_bar;

public:

Foo();

~Foo();

}



In Foo.cpp

#include "Bar.h" // a change to Bar.h only causes Foo to recompile not
everthing that includes Foo.



Foo::Foo() :

m_bar = 0;

{

m_bar = new Bar;

}



Foo::~Foo()

{

if (m_bar)

{

delete m_bar;

m_bar = 0;

}

}



I hope this helps.

Mark
 
J

Jim Langston

wiskey5alpha said:
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 ?

As others are stating,
Bar m_bar;
is preferred. When you can't, for whatever reason, then you would use a
pointer
Bar* m_bar;
or wrap Bar in a class hiding the pointer. Using pointers when you don't
have to brings up maintance issues that you have to remember to deal with,
new if you need to, if you do new make sure you delete, point it to the
correct place if you're not newing it, etc... Pointers are a level of
indirection and you should only add a layer of indirection when you have to,
or there is a good sound design issue it resolves.
 
M

mlimber

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-lite/ctors.html#faq-10.18).

Also, to prevent memory leaks, you should generally use smart pointers
(cf. http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.22
and the following FAQs) and RAII containers like std::vector (http://
www.parashift.com/c++-faq-lite/containers.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-lite/exceptions.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<Bar> if
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,679
Members
48,796
Latest member
Greg L.

Latest Threads

Top