Using pointer or reference?

D

Duane Hebert

Evan said:
i = new int; you mean. ;-)


But to answer your question, I think the argument goes that it doesn't
help much when you're WRITING the code, but if you're thrown into some
system you probably don't want to check the signature of every function
that's used. (Especially if you're using an editor without good code
browsing abilities (right click, got to declaration).) Ideally then if
you see a call "foo(x)" you'd like to know at the call site if x could
change or if foo's a pure function. Even C falls flat on its face in
this regard, so I don't think that references hurt it too much.

OK. Now I get get what Daniel is saying. I thought he
was arguing that using pointers somehow solved this.
No, in this respect I don't see that it matters.
Sorry for wasting the bandwidth.
 
D

Daniel T.

Duane said:
When passing by value, the variable can't be modified.

And when passing by const reference the value can't be modified so do
you never pass by value?

"Use reference when you can, use pointers when you must" doesn't cover
when you should pass by value.
As for when you need a pointer, you need it if it can be null.

You can always redesign the function so that passing a null is
invalid/undefined.
You also need it when you want to reassign it.

You can do that with references:

void fn( int& i ) {
i = 65;
}
 
D

Daniel T.

Duane said:
You seem to be saying to prefer pointers over references because
with references you can't know if the variable is going to be
modified by the function. Sorry if I didn't get your point then...

I'm saying that in any case where you can use a reference (except
operator overloads) you can use a pointer. Prefer whichever you want,
but it is merely preference, there is no compelling reason to use one
over the other.

My own preference is to use them as a documentation tool. I use a
pointer if the calling code can't destroy the object immediatly upon
exit of the function, and a reference if it can.
 
D

Duane Hebert

Daniel T. said:
And when passing by const reference the value can't be modified so do
you never pass by value?

I usually pass by value when I want to give the function
a copy of the value and it's not large. Passing an int
by non const reference makes no sense to me. Nor does passing
a vector by value instead of const reference.

"Use reference when you can, use pointers when you must" doesn't cover
when you should pass by value.

When should you pass by value except when it's more efficient
than a const & ?
You can always redesign the function so that passing a null is
invalid/undefined.

If it's your function.
You can do that with references:

void fn( int& i ) {
i = 65;
}

This is not what I mean. Perhaps I should have
said reseating or something.
 
D

Duane Hebert

Duane Hebert said:
I usually pass by value when I want to give the function
a copy of the value and it's not large. Passing an int
by non const reference makes no sense to me. Nor does passing

That should be "passing an int by const & makes no sense to me. "
 
D

Daniel T.

Duane said:
I usually pass by value when I want to give the function a copy of
the value and it's not large. Passing an int by non const reference
makes no sense to me. Nor does passing a vector by value instead of
const reference.


When should you pass by value except when it's more efficient than a
const & ?

OK, so add that to the formulation. That's all I'm saying here, the
quote you provided doesn't tell the whole story because you can use
references even where passing by value makes more sense.
If it's your function.

If it isn't our function, then we aren't going to be making any
decisions about what the parameter types are. The discussion assumes we
are the one's making the decision, so of course it's our function.
This is not what I mean. Perhaps I should have said reseating or
something.

Reseating a pointer within a function has no effect on the calling
function either. Your previous example, as I pointed out, was
pointless.

When designing a function, we can make the parameter type T, const T&,
T&, const T*, or T*. The OP asked how to decide between the five
options. I'm interested in your answer. How do you decide between them?
Can your formulate your decision process as an algorithm?
 
D

Duane Hebert

Daniel T. said:
OK, so add that to the formulation. That's all I'm saying here, the
quote you provided doesn't tell the whole story because you can use
references even where passing by value makes more sense.

Your example of passing &i is what caught my attention. I just
had to clean up a bunch of code written by a former employee.
He decided to write functions that took a std::vector*. When he
called these functions, if he had a std::vector, he passed it
by &vec. He didn't like iterators.

If it isn't our function, then we aren't going to be making any
decisions about what the parameter types are. The discussion assumes we
are the one's making the decision, so of course it's our function.


Reseating a pointer within a function has no effect on the calling
function either. Your previous example, as I pointed out, was
pointless.

Well you can dereference a pointer and do pretty much
what you want with it.
When designing a function, we can make the parameter type T, const T&,
T&, const T*, or T*. The OP asked how to decide between the five
options. I'm interested in your answer. How do you decide between them?
Can your formulate your decision process as an algorithm?

Not really as an algorithm. It would be nice if you could
create algorithms to tell you how to design software
on this level but it would be hard to cover all the possibilities.

Sometimes you need to use pointers. For
example, if you use Borland's VCL, all of their TObject stuff must
be pointers. With Qt, it's often the case though not exclusively.

When you write functions, you don't always get to choose the
types that you're working with.

But given generic code, assuming that I don't want to modify
the variable, if it's no more efficient to use a reference, I would
just pass it by value.

If the object is expensive to copy like a vector<spoo>, I would
use const &.

Beyond that, it depends on the circumstances.
 
E

Evan

When designing a function, we can make the parameter type T, const T&,
T&, const T*, or T*. The OP asked how to decide between the five
options. I'm interested in your answer. How do you decide between them?
Can your formulate your decision process as an algorithm?

Hmm, here's my thoughts... not sure if I follow this exactly myself,
but I'll give it a shot.

if( there does not need to be a way to express "no value" )
{
if( parameter is just an in parameter )
{
if( the type is sufficiently small so the overhead of
copying is less than the overhead of accessing
it through a pointer)
{
pass by value
}
else
{
if( the function is C++ only)
pass by const reference
else // it needs to be callable from C
pass by const pointer
}
}
else
{ // parameter is out or inout
if( the function is C++ only )
pass by reference
else
pass by pointer
}
}
else
{ // there needs to be a way to express "no value"
if( parameter is an in parameter )
pass by const pointer
else
pass by pointer
}

Wow, that's actually pretty complicated...
 
D

Duane Hebert

Evan said:
Hmm, here's my thoughts... not sure if I follow this exactly myself,
but I'll give it a shot.

if( there does not need to be a way to express "no value" )
{
if( parameter is just an in parameter )
{
if( the type is sufficiently small so the overhead of
copying is less than the overhead of accessing
it through a pointer)
{
pass by value
}
else
{
if( the function is C++ only)
pass by const reference
else // it needs to be callable from C
pass by const pointer
}
}
else
{ // parameter is out or inout
if( the function is C++ only )
pass by reference
else
pass by pointer
}
}
else
{ // there needs to be a way to express "no value"
if( parameter is an in parameter )
pass by const pointer
else
pass by pointer
}

Wow, that's actually pretty complicated...

Yeah but it covers most options. It's
about the way that I look at it as well.
 
D

Daniel T.

Evan said:
Hmm, here's my thoughts... not sure if I follow this exactly myself,
but I'll give it a shot.

if( there does not need to be a way to express "no value" )
{
if( parameter is just an in parameter )
{
if( the type is sufficiently small so the overhead of
copying is less than the overhead of accessing
it through a pointer)
{
pass by value
}
else
{
if( the function is C++ only)
pass by const reference
else // it needs to be callable from C
pass by const pointer
}
}
else
{ // parameter is out or inout
if( the function is C++ only )
pass by reference
else
pass by pointer
}
}
else
{ // there needs to be a way to express "no value"
if( parameter is an in parameter )
pass by const pointer
else
pass by pointer
}

Wow, that's actually pretty complicated...

Well then, let's refactor it.

(a) The first 'if' can be summarily decided as 'false'. There is no
compelling reason to allow the caller to express "no value".

(b) Since this is a C++ forum, let's assume C++ throughout.

So it becomes:

if ( in parameter only )
if ( sizeof parameter <= sizeof int )
pass by value
else
pass by const reference
else
pass by reference

Hmm...

One thing it misses is what to do if the parameter is supposed to
represent an array, but if one consistently uses 'vector' for arrays,
that removes it as a need.

So you only pass by pointer if the function needs to be callable from C
or if you choose to allow the caller to pass in NULL. Is that correct?
 

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,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top