pointer versus reference in constructors

J

johny smith

I never really know if I should use references or pointers for constructors.

Can anyone give me some guidance on when to use what?

My back ground is C, so I tend to use pointer notation, but really don't
know what the advantage of the reference it.

Thanks alot.

ex. of two constructors

Car( Engine* engine )

or,

Car( Engine& engine)
 
J

JKop

johny smith posted:
I never really know if I should use references or pointers for
constructors.

Can anyone give me some guidance on when to use what?

My back ground is C, so I tend to use pointer notation, but really
don't know what the advantage of the reference it.

Thanks alot.

ex. of two constructors

Car( Engine* engine )

or,

Car( Engine& engine)


class Car
{
Engine* engine;
}


If you have the above, then you're looking to store the address of an engine
object, so you'll want to take a Engine* in the contructor.


class Car
{
Engine engine;
}


If you have the above, then you're looking to copy an actual engine supplied
from elsewhere. Here you may use Engine or Engine&. Engine& prevents a
temporary object being created, so use it. Although ofcourse you could use
an Engine* for this purpose aswell, but the Engine& just saves you typing
the asterisk.


-JKop
 
D

DaKoadMunky

A pointer can be initialized with 0.

A reference may not be initialized with 0.

Is it reasonable that your car be constructed without an engine? If so, use a
pointer. If not, use a reference.

If your design requires a car be constructed with an engine then using a
reference helps to enforce that constraint at compile-time. Using a pointer
would move enforcement of that constraint to run-time.

Note: As shown by Scott Meyers in his "Effective C++" series it is possible to
have a null reference...

T *ptr = 0;
T &ref = *ptr;

....but he refers to such usage as evil and states something to the effect that
the author of such code deserves whatever fate befalls them.

One of his "Effective C++" books contains a nice entry on the differences
between pointers and references and how to determine when each is appropriate.
 
J

JKop

DaKoadMunky posted:
Note: As shown by Scott Meyers in his "Effective C++" series it is
possible to have a null reference...

T *ptr = 0;
T &ref = *ptr;

...but he refers to such usage as evil and states something to the
effect that the author of such code deserves whatever fate befalls
them.


Even if they win a life-time supply of ice-cream, strawberry syrup and 100s
'n' 1000s?


-JKop
 
D

DaKoadMunky

class Car
{
Engine* engine;
}


If you have the above, then you're looking to store the address of an engine
object, so you'll want to take a Engine* in the contructor.

IMO storing a pointer to an Engine does not negate the idea of using references
as function arguments to express the notion that users of Car must specify an
Engine at construction and when the need arises to replace the engine...

class Car
{
public:

Car(Engine& engine) //Can't be null
:m_engine(&engine)
{
}

void ReplaceEngine(Engine& engine) //Can't be null
{
m_engine = &engine;
}

private:

Engine* m_engine;
};

Depending on how an Engine is allocated it is possible that any run-time check
for failure will need to be dealt with elsewhere, but at the minimum Car should
not have to worry about whether or not it has an engine to forward commands to.

Just my opinion. If the gurus disagree, please let me know. I am here to
learn.
 
L

Luther Baker

DaKoadMunky said:
...

class Car
{
public:

Car(Engine& engine) //Can't be null
:m_engine(&engine)
{
}

void ReplaceEngine(Engine& engine) //Can't be null
{
m_engine = &engine;
}

private:

Engine* m_engine;
};

Depending on how an Engine is allocated it is possible that any run-time check
for failure will need to be dealt with elsewhere, but at the minimum Car should
not have to worry about whether or not it has an engine to forward commands to.

Just be careful. Overall, the design isn't any safer ...

What if an engine is create on the stack - and then passed into this
constructor ... and then the engine goes out of scope :(

Its all contextual of course, but it might be better to actually copy
the engine into the car and not try to maintain a pointer to an engine
created outside the Car.

--------------------------------

#include <iostream>

struct Engine
{
public:

void start () const
{
std::cout << "starting ..." << std::endl;
}
};

struct Car
{
public:
Car(Engine& eng)
: engine(&eng)
{
}
const Engine* get_engine () const
{
return engine;
}
private:
Engine* engine;
};

class Mechanic
{

public:

Car* create_car ()
{
// bad decision, but it compiles and might even run
Engine engine;
Car* car = new Car(engine);
return car;
}
};

int
main(int argc, char** argv)
{
Mechanic m;
Car* car = m.create_car ();
const Engine* engine = car->get_engine ();

// EEK --- where is the car's engine?
engine->start();

delete car;
return 0;
}

--------------------------------


In this toy program, the address still holds (VC++ 7.1) so the program
runs ... but its undefined behavior since the Engine has long since gone
out of scope.

Hth,

-Luther
 
D

Dave Townsend

Just one more issue which didn't get mentioned in the thread:

Typically Engine could well be a base class for a variety of
engine classes, so you would use a pointer to the base class of
Engine as the member...

Car myCar( new V8Engine() );
Car yourCar( new HybridEngine() );

dave.
 
M

Michiel Salters

johny smith said:
I never really know if I should use references or pointers for constructors.

Can anyone give me some guidance on when to use what?

My back ground is C, so I tend to use pointer notation, but really don't
know what the advantage of the reference it.

Thanks alot.

ex. of two constructors

Car( Engine* engine )

or,

Car( Engine& engine)

Probably every car has its own engine, so you'd need an EngineFactory.
Since this is not optional, you'd use a &. A pointer suggests it could
be NULL.

Depending on the complexity, Car either holds an Engine object (in which
case the Engine ctor takes a EngineFactory) or a [smart] Engine pointer
( in which case the Engine ctor is private and EngineFactory has a
ptr<Engine> create() member ).

Regards,
Michiel Salters.
 
B

Bill Seurer

DaKoadMunky said:
Note: As shown by Scott Meyers in his "Effective C++" series it is possible to
have a null reference...

T *ptr = 0;
T &ref = *ptr;

It "is possible" if references are implemented as pointers under the
covers which is not required.
 
K

Kench

JKop said:
johny smith posted:



class Car
{
Engine* engine;
}


If you have the above, then you're looking to store the address of an engine
object, so you'll want to take a Engine* in the contructor.


class Car
{
Engine engine;
}


If you have the above, then you're looking to copy an actual engine supplied
from elsewhere. Here you may use Engine or Engine&. Engine& prevents a
temporary object being created, so use it. Although ofcourse you could use
an Engine* for this purpose aswell, but the Engine& just saves you typing
the asterisk.


-JKop
I second this, because if I am using the Car class in my code,
without looking at the Car class code
if constuctor is Car(Engine* engine) I would think that Car will just
keep a pointer to Engine
if constuctor is Car(Engine& engine) I would think that Car keeps its own
copy of Engine.
thanks
 
V

Victor Bazarov

Kench said:
I second this, because if I am using the Car class in my code,
without looking at the Car class code
if constuctor is Car(Engine* engine) I would think that Car will just
keep a pointer to Engine
if constuctor is Car(Engine& engine) I would think that Car keeps its own
copy of Engine.

It might be even helpful in some cases to do

Car(Engine const& engine)

if 'Car' keeps its own copy. Making the reference const allows it to be
bound to a temporary (as in returned from a function, for example, or
created on the fly from another type, like with 'std::string' created
from a string literal).

Keeping the reference non-const can be useful if the construction process
needs to somehow alter the object to which the reference refers (whatever
that altering happens to be).

Victor
 
B

Bill Seurer

Kench said:
I second this, because if I am using the Car class in my code,
without looking at the Car class code
if constuctor is Car(Engine* engine) I would think that Car will just
keep a pointer to Engine
if constuctor is Car(Engine& engine) I would think that Car keeps its own
copy of Engine.

Then you don't understand how references work.

Or did you mean that you see...

new Car(engine);

versus

new Car(&engine);

and are confused about what the constructor does? I hope that you
always check what the constructor you are calling does whether it takes
pointers, references, or whatever.
 
J

Jeff Schwab

johny said:
I never really know if I should use references or pointers for constructors.

Can anyone give me some guidance on when to use what?

My back ground is C, so I tend to use pointer notation, but really don't
know what the advantage of the reference it.

Thanks alot.

ex. of two constructors

Car( Engine* engine )

or,

Car( Engine& engine)

I've almost always found it better to use the reference. Why make the
user of your class deal with pointers more than necessary? (I don't
hate pointers, I just don't think they're necessary here.)
 
D

Daniel T.

johny smith said:
I never really know if I should use references or pointers for constructors.

Can anyone give me some guidance on when to use what?

My back ground is C, so I tend to use pointer notation, but really don't
know what the advantage of the reference it.

Thanks alot.

ex. of two constructors

Car( Engine* engine )

or,

Car( Engine& engine)

The answer depends on how you expect Car to be used. Do you want clients
to be able to do:

Car myCar( new Engine );

If so, then the pointer c_tor would be best (obviously here the Car must
take control of the lifetime of the engine passed in.) If clients should
be able to do:

Engine e;
Car myCar( e );

then the reference c_tor is best... (here the car is not taking control
of the lifetime of the object passed in, it is either sharing the
engine, or making a copy of the engine.)


IN GENERAL: Whenever you aren't sure which interface would be better
(and this is certainly an interface issue) always look at the problem
from the perspective of the clients of the class, *not* the
implementation of the class.
 
D

Daniel T.

I never really know if I should use references or pointers for
constructors.

Can anyone give me some guidance on when to use what?

My back ground is C, so I tend to use pointer notation, but really
don't know what the advantage of the reference it.

Thanks alot.

ex. of two constructors

Car( Engine* engine )

or,

Car( Engine& engine)


class Car
{
Engine* engine;
}


If you have the above, then you're looking to store the address of an engine
object, so you'll want to take a Engine* in the contructor.


class Car
{
Engine engine;
}


If you have the above, then you're looking to copy an actual engine supplied
from elsewhere. Here you may use Engine or Engine&. Engine& prevents a
temporary object being created, so use it. Although ofcourse you could use
an Engine* for this purpose aswell, but the Engine& just saves you typing
the asterisk.[/QUOTE]

I think that basing the answer on how Car is implemented is not the way
to go.
 
D

Daniel T.

A pointer can be initialized with 0.

A reference may not be initialized with 0.

Is it reasonable that your car be constructed without an engine? If so, use a
pointer. If not, use a reference.

If your design requires a car be constructed with an engine then using a
reference helps to enforce that constraint at compile-time. Using a pointer
would move enforcement of that constraint to run-time.

Your logic is impeccable of course, however I'm afraid one could end up
with code like:

Car myCar( *new Engine );

Which seems just a little off to me. Your guideline is yet another
example of basing the interface on the needs of the server (Car in this
case) rather than the clients that use that server.
 
J

Jeff Schwab

DaKoadMunky said:
A pointer can be initialized with 0.

A reference may not be initialized with 0.

Is it reasonable that your car be constructed without an engine? If so, use a
pointer. If not, use a reference.

I don't think that's a particularly good reason to use pointers, though
it's not a particularly bad one, either. It's always possible to have a
separate constructor for the no-engine case, perhaps taking an object of
some custom type like struct Car::No_engine, an enumerator like
Car::engineless (a la ios::* flags) or using a static object that is the
"null engine."
 
J

Jeff Schwab

Daniel said:
The answer depends on how you expect Car to be used. Do you want clients
to be able to do:

Car myCar( new Engine );

If so, then the pointer c_tor would be best (obviously here the Car must
take control of the lifetime of the engine passed in.) If clients should
be able to do:

Engine e;
Car myCar( e );

then the reference c_tor is best... (here the car is not taking control
of the lifetime of the object passed in, it is either sharing the
engine, or making a copy of the engine.)

I'm not sure I like the

Car car( new Engine );

idea, since it's unclear without further documentation who is
responsible for deleting the engine, and I find this:

Car car( *new Engine );

equally readable. If the idea is to be able to support whichever style
the client prefers, though, then it should be noted that the two styles
presented here aren't mutually exclusive; it's entirely possible to
provide constructors for both usage models, perhaps using an extra level
of inheritance to encapsulate the commonality of the constructors:

Car( Engine* engine ): Car_base( *engine ) { }
Car( Engine& engine ): Car_base( engine ) { }

Of, if you like:

Car( Engine* engine ): Car_base( engine ) { }
Car( Engine& engine ): Car_base( &engine ) { }
IN GENERAL: Whenever you aren't sure which interface would be better
(and this is certainly an interface issue) always look at the problem
from the perspective of the clients of the class, *not* the
implementation of the class.

Right on.
 
E

E. Robert Tisdale

johny said:
I never really know if I should [pass] references or pointers [to] constructors.

A reference is always preferred.
Can anyone give me some guidance on when to use what?

My back ground is C, so I tend to use pointer notation,
but really don't know what the advantage of the reference it.



ex. of two constructors

Car::Car(Engine* pEngine)

or

Car::Car(Engine& engine)

Always try to pass a const reference

Car::Car(const Engine& engine)

Never use a pointer unless you need to "reseat" it.
 

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,169
Messages
2,570,920
Members
47,462
Latest member
ChanaLipsc

Latest Threads

Top