When to use pointers in a class?

J

Joe Van Dyk

Is there some rule of thumb about when to use pointers to an object and
when to use a reference* to an object when a class needs to have objects
as data members?

Example:
class A
{
B* b_ptr;
B b;
vector<B*> vector_ptrs;
vector<B> vector_objects;
};

How do I know when to use pointers and when not to use them?

Thanks,
Joe

* I'm not sure if my terminology is correct here, please correct me if
I'm wrong. I'm also slightly confused about the relationship between
references and pointers. I know a reference is an alias of an object
and a pointer contains some address that's usually the start of the
object's location in memory, but I'm still not sure what the real
difference is.
 
P

Phlip

Joe said:
Is there some rule of thumb about when to use pointers to an object and
when to use a reference to an object when a class needs to have objects
as data members?

Prefer a reference unless you need a pointer's extra features.
Example:
class A
{
B* b_ptr;

Prefer a reference (seated in A::A), unless you need b_ptr==NULL for special
situations.

Then, as your designing gets more advanced, create a NullB, derived from B,
for use when there's no B, and seat or point b_ptr to it. NULL pointers
should be replaced with Null Objects that do nothing. This simplifies the
calling code.
B b;
vector<B*> vector_ptrs;

A pointer can be copied as an object, so you can't use a reference there. (I
doubt the template will even expand on one.
vector<B> vector_objects;

That is a copy, not a reference. Prefer one, if B is cleanly copiable, in
preference to pointers _or_ references.

The simpler the better.
* I'm not sure if my terminology is correct here, please correct me if
I'm wrong. I'm also slightly confused about the relationship between
references and pointers. I know a reference is an alias of an object
and a pointer contains some address that's usually the start of the
object's location in memory, but I'm still not sure what the real
difference is.

Sometimes a reference is a pointer with the indirection * already turned on.
That's how to start thinking about them, but the alias definition is more
powerful because the language permits subtle optimizations, such as
temporaries, via that definition.
 
H

Howard

Phlip said:
Prefer a reference unless you need a pointer's extra features.

As a data member? Why? I rarely use references as members.

I'd say prefer to use a member object (such as the member 'b' in the
example) over pointer members (such as member 'b_ptr' in the example).

Perhaps you're thinking of function parameters? For those, I'd agree that a
reference (or const reference) may be preferable to a pointer, unless there
is some need for a pointer, such as allowing a NULL value.
Prefer a reference (seated in A::A), unless you need b_ptr==NULL for
special
situations.

I don't understand. You mean you'd prefer

class A
{
B& b;
//...
};

over

class A
{
B b;
//...
};

....?

Sounds like you're assuming that an instance of B resides outside the A
class, prior to the construction of an instance of A, which is available to
pass to A's constructor. But the OP made no such inference.
Then, as your designing gets more advanced, create a NullB, derived from
B,
for use when there's no B, and seat or point b_ptr to it. NULL pointers
should be replaced with Null Objects that do nothing. This simplifies the
calling code.


A pointer can be copied as an object, so you can't use a reference there.
(I
doubt the template will even expand on one.


That is a copy, not a reference. Prefer one, if B is cleanly copiable, in
preference to pointers _or_ references.

Well, there are at least two reasons why I might (and usually do, in
practice) prefer pointers in vectors over objects. One is that I might want
to make use of polymorphism, and I can only do that with a pointer or
reference. The other is that the copying of objects _may_ be expensive or
otherwise undesired.

Smart pointers as vector members, I am told, are an even better solution in
many cases.

-Howard
 
P

Phlip

Howard said:
As a data member? Why? I rarely use references as members.

I rarely write new C++ code. My job is troubleshooting existing C++. Code
that learned the C style, such as pointer abuse, drives me nuts. It doesn't
necessarily slow me down, though.

Maybe your members frequently repoint to other objects? Then you need
pointers.
Perhaps you're thinking of function parameters? For those, I'd agree that
a reference (or const reference) may be preferable to a pointer, unless
there is some need for a pointer, such as allowing a NULL value.

Same rule; use a pointer only if you need its extra features.

Now read MFC code, or C++ code driving RenderWare. Everyone passes pointers
everywhere, even where passing a NULL makes no sense, even where a
NullObject would work perfectly. Bleah!
I don't understand. You mean you'd prefer

class A
{
B& b;
//...
};

over

class A
{
B b;
//...
};

...?

If A can own the B, use the last one. It's the _weakest_ construction, with
the _least_ extra features.
Sounds like you're assuming that an instance of B resides outside the A
class, prior to the construction of an instance of A, which is available
to
pass to A's constructor. But the OP made no such inference.

I did. I ass-u-me-d that the OP knew to prefer member objects over handles
of any kind.
Well, there are at least two reasons why I might (and usually do, in
practice) prefer pointers in vectors over objects. One is that I might
want to make use of polymorphism, and I can only do that with a pointer or
reference. The other is that the copying of objects _may_ be expensive or
otherwise undesired.

When you need the extra features pointers provide, use them.
Smart pointers as vector members, I am told, are an even better solution
in many cases.

If they are indeed smart enough ;-)
 
J

Joe Van Dyk

Phlip said:
Joe Van Dyk wrote:




Prefer a reference unless you need a pointer's extra features.

In which situations would I want a pointer's extra features, and what
are those extra features?
Prefer a reference (seated in A::A), unless you need b_ptr==NULL for special
situations.

By "seated in A::A", you mean put into A's constructor?
Then, as your designing gets more advanced, create a NullB, derived from B,
for use when there's no B, and seat or point b_ptr to it. NULL pointers
should be replaced with Null Objects that do nothing. This simplifies the
calling code.




A pointer can be copied as an object, so you can't use a reference there. (I
doubt the template will even expand on one.




That is a copy, not a reference. Prefer one, if B is cleanly copiable, in
preference to pointers _or_ references.

Would a reference to vector objects look like:
vector<B&> vector_objects
?

If I had the following function:
void add_stuff_to_the_vector()
{
B b;
b.foo = "Hello"
vector_objects.push_back(b);
}

Would that be ok? The push_back'd object that there's a reference to in
the vector wouldn't disappear after the function ends?
The simpler the better.




Sometimes a reference is a pointer with the indirection * already turned on.
That's how to start thinking about them, but the alias definition is more
powerful because the language permits subtle optimizations, such as
temporaries, via that definition.

Hmm.. ok. I'll ponder that one.

Thanks, you've been quite helpful!

Joe
 
L

loufoque

Joe Van Dyk wrote :
Is there some rule of thumb about when to use pointers to an object and
when to use a reference* to an object when a class needs to have objects
as data members?

If you don't need pointers, dont use pointers.
 
H

Howard

Joe Van Dyk said:
Is there some rule of thumb about when to use pointers to an object and
when to use a reference* to an object when a class needs to have objects
as data members?

Example:
class A
{
B* b_ptr;
B b;
vector<B*> vector_ptrs;
vector<B> vector_objects;
};

How do I know when to use pointers and when not to use them?

Thanks,
Joe

* I'm not sure if my terminology is correct here, please correct me if I'm
wrong.

Your question asks about something you called "reference*". There's no such
thing as a "reference*". Did you just mean "reference"?

Also, your example shows a B* pointer member and a B object member , and
doesn't show any reference members at all.

So I guess I'm confused as to what your question really means.

I'm also slightly confused about the relationship between references and
pointers. I know a reference is an alias of an object and a pointer
contains some address that's usually the start of the object's location in
memory, but I'm still not sure what the real difference is.

A good book will help you the most here.

-Howard
 
S

Simon Elliott

Is there some rule of thumb about when to use pointers to an object
and when to use a reference* to an object when a class needs to have
objects as data members?

Example:
class A
{
B* b_ptr;
B b;
vector<B*> vector_ptrs;
vector<B> vector_objects;
};

How do I know when to use pointers and when not to use them?

Let's look at another example:

class A
{
B* b_ptr; // pointer to B
B& b_ref; // reference to B
};

Using the reference is more restrictive. You must assign the reference
in A's constructor. So the instance of B which b_ref is referring to
must exist before A is created. You can't decide part way through the
life of A to change b_ref to refer to a different instance of B (ie you
can't reseat a reference.) If your design allows you to live with these
restrictions, the use of a reference will help you to write more
error-free code and will help other programmers who read your code.

Using the pointer, you can do these things which you can't do with a
reference:

* You can assign b_ptr at a point later than when A is constructed.
This can be useful in class factories, avoiding brittle constructors
etc. It can also be useful where an instance of B can't be created
before the instance of A.

* A can assume ownership of b_ptr, creating it with 'new' in A's
constructor, deleting it in A's destructor.

* b_ptr can be reassigned to point to a different B part way through
the lifetime of A.

* b_ptr can be null, can point to a deleted object, can be
uninitialised so it points to a random memory location. These all
result in the sort of errors which can be hard to track down. (OK, you
can do some of the above with a reference, but you have to work harder
at it!)
 
H

Howard

Joe Van Dyk said:
In which situations would I want a pointer's extra features, and what are
those extra features?

I mentioned two reasons in my post earlier in this sub-thread.


Would a reference to vector objects look like:
vector<B&> vector_objects
?

That's not allowed in C++.

That would declare a vector of references to B objects, not a "reference to
vector objects". I suspect this is what you meant, but you should be sure
of it, especially since what you wrote isn't legal C++.
If I had the following function:
void add_stuff_to_the_vector()
{
B b;
b.foo = "Hello"
vector_objects.push_back(b);
}

Would that be ok? The push_back'd object that there's a reference to in
the vector wouldn't disappear after the function ends?

As I said above, you can't put references in a vector, so no point trying to
fill it, eh? :)

-Howard
 
J

Joe Van Dyk

Howard said:
Your question asks about something you called "reference*". There's no such
thing as a "reference*". Did you just mean "reference"?

The '*' was a footnote indicator.
Also, your example shows a B* pointer member and a B object member , and
doesn't show any reference members at all.

So I guess I'm confused as to what your question really means.

Me too. :(
A good book will help you the most here.

I'm still making my way through the good books.
 
J

Joe Van Dyk

Joe said:
Is there some rule of thumb about when to use pointers to an object and
when to use a reference* to an object when a class needs to have objects
as data members?

Related question:

I have a class that looks like this:


class Image
{
public:
typedef unsigned int color_type;
Image(size_t width, size_t height);
void write(const std::string& image_file_name);
void set_pixel(size_t x, size_t y,
color_type r, color_type g, color_type b);

private:
Magick::Image &_image;
Magick::Geometry &(geometry;
Magick::ColorRGB &_background_color;
};

(documentation on ImageMagick++ is at
http://www.simplesystems.org/Magick++/Documentation.html)

Quick overview: a Magick::Image takes in its constructor a Geometry and
a Color. A Magick::Geometry takes in its constructor a width and a
height. And the Magick::ColorRGB object takes nothing in its constructor.

Do I want to use references to the member objects here? Or pointers?
I'm having difficulties initializing the objects if they are references
and aren't passed in to the Image constructor.

Thanks,
Joe
 
J

Joe Van Dyk

Joe said:
Related question:

I have a class that looks like this:


class Image
{
public:
typedef unsigned int color_type;
Image(size_t width, size_t height);
void write(const std::string& image_file_name);
void set_pixel(size_t x, size_t y,
color_type r, color_type g, color_type b);

private:
Magick::Image &_image;
Magick::Geometry &(geometry;

oops
Magick::Geometry &_geometry;
 
D

Daniel T.

Joe Van Dyk said:
Is there some rule of thumb about when to use pointers to an object and
when to use a reference* to an object when a class needs to have objects
as data members?

Example:
class A
{
B* b_ptr;
B b;
vector<B*> vector_ptrs;
vector<B> vector_objects;
};

How do I know when to use pointers and when not to use them?

Think of a reference as a const pointer that can't be NULL, and uses
object syntax. IE:

B& rb;
B* const pb;

Are very much alike in their behavior. For rb you do "rb.someFunc()" for
pb you do "pb->someFuc()"

Here are some basic rules of thumb...

As member-variables: prefer by-value. If you need to hold something that
is being shared among several objects, then use a pointer. If you need
to hold something that is an Abstract Base Class (ABC) then use a
pointer.

A vector template defines a vector's member-variables so use the same
rule as above for making one. IE prefer vector<B> unless the things
contained in the vector are being shared or B is an abstract base class.
 
S

Squeamizh

Joe said:
Is there some rule of thumb about when to use pointers to an object and
when to use a reference* to an object when a class needs to have objects
as data members?

One important thing to keep in mind is that if a class contains a
reference, then instances of it cannot be contained in an STL
container*. It is not always easy to know when you're designing the
class if this is something you'll need to do in the future or not.

* Assuming there isn't an assignment operator that doesn't touch the
reference.
 
J

Jim Langston

Joe Van Dyk said:
Is there some rule of thumb about when to use pointers to an object and
when to use a reference* to an object when a class needs to have objects
as data members?

Example:
class A
{
B* b_ptr;
B b;
vector<B*> vector_ptrs;
vector<B> vector_objects;
};

How do I know when to use pointers and when not to use them?

Thanks,
Joe

* I'm not sure if my terminology is correct here, please correct me if I'm
wrong. I'm also slightly confused about the relationship between
references and pointers. I know a reference is an alias of an object and
a pointer contains some address that's usually the start of the object's
location in memory, but I'm still not sure what the real difference is.

I would say use a pointer if you need polymorphism. You can't get
polymorphism through a reference (my understanding anyway). Also, you can
reassign a pointer, you can't reassign a reference. The reference needs to
be set in the constructor initialization list, so the object being
referenced has to exist before the consturctor.
 
H

Howard

I would say use a pointer if you need polymorphism. You can't get
polymorphism through a reference (my understanding anyway).

Yes, you can. Polymorphism doesn't come into play when making calls
directly on an object's methods, but it does when making calls on the object
through a pointer or reference to it.
Also, you can reassign a pointer, you can't reassign a reference. The
reference needs to be set in the constructor initialization list, so the
object being referenced has to exist before the consturctor.

-Howard
 
I

Ian Collins

Jim said:
I would say use a pointer if you need polymorphism. You can't get
polymorphism through a reference (my understanding anyway). Also, you can
reassign a pointer, you can't reassign a reference. The reference needs to
be set in the constructor initialization list, so the object being
referenced has to exist before the consturctor.
Yes you can get polymorphism through a reference.

If the object being referenced exists when the container is constructed,
knowing the object is there saves the code form checking a pointer for
NULL.

If the contained object can be replaced, then yes, use a pointer.
 
J

Jim Langston

Howard said:
Yes, you can. Polymorphism doesn't come into play when making calls
directly on an object's methods, but it does when making calls on the
object through a pointer or reference to it.


-Howard

Wow, you're right. My understanding was wrong. The output of the following
program is "derived".

#include <iostream>
#include <string>

class base
{
public:
virtual method() { std::cout << "base" << std::endl; }
};

class derived: public base
{
public:
method() { std::cout << "derived" << std::endl; }
};

int main ()
{
derived MyDerived;
base& baseref = MyDerived;
baseref.method();

std::string wait;
std::cin >> wait;
}
 

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,432
Messages
2,571,681
Members
48,796
Latest member
Greg L.

Latest Threads

Top