passing pointer to struct by reference

M

Mike

Consider the following code:

"""
struct person {
char *name;
int age;
};

typedef struct person* StructType;

/* Think I got that syntax right above... :) */

void somefunc(StructType t)
{
// do something
}

int main()
{
StructType st;
somefunc(st);
}
"""

My professor called me out on my invocation of somefunc() by saying that
I should be passing by reference instead. My response was "Well, it's
*really* a pointer anyways, so what does it matter?" Now that I think
about this, I guess you should always pass by reference because you may
not always know if something is represented as a pointer. Is this the
reason? I have done more C than C++ so by nature I tend to focus on
pointers :)

Thanks.

Mike
 
A

Alf P. Steinbach

* Mike:
Consider the following code:

"""
struct person {
char *name;
int age;
};

typedef struct person* StructType;

/* Think I got that syntax right above... :) */

void somefunc(StructType t)
{
// do something
}

int main()
{
StructType st;
somefunc(st);
}
"""

My professor called me out on my invocation of somefunc() by saying that
I should be passing by reference instead. My response was "Well, it's
*really* a pointer anyways, so what does it matter?"

With a pointer you're saying: "I'm supporting a null-pointer argument".

With a reference you're saying: "This won't ever be a null-pointer".

There's less checking and less that can go wrong. For example, in the
above code you're passing an uninitialized pointer. That's Undefined
Behavior.

Better naming can also help.

Here the pointerness is hidden behind a name that doesn't signify
pointer, so it's possible your professor didn't even see the UB or the
null-pointer issue but just assumed you were passing a structure
(inefficiently) by value.

Now that I think
about this, I guess you should always pass by reference because you may
not always know if something is represented as a pointer. Is this the
reason? I have done more C than C++ so by nature I tend to focus on
pointers :)

Mostly, passing by reference (to const) instead of passing by value is
an optimization that very seldom hurts, and very often helps. Although
the compiler can do the same optimization, you don't have to worry about
whether it does. And doing this can clean up the design and help
improve your own understanding of the code... ;-)

Passing by pointer instead of by value is, on the other hand, an
optimization that often hurts, and muddles the waters instead of
clarifying anything.
 
A

Artie Gold

Mike said:
Consider the following code:

"""
struct person {
char *name;
int age;
};

typedef struct person* StructType;

Hiding a pointer type like this is, IMHO, ugly.
/* Think I got that syntax right above... :) */

void somefunc(StructType t)
{
// do something

Do something?
Well, what you're planning to do here is *very* relevant!
}

int main()
{
StructType st;
somefunc(st);
As stated here, you're passing an unitialized pointer to a function
returning void. What could you *possibly* be doing?
}
"""

My professor called me out on my invocation of somefunc() by saying that
I should be passing by reference instead. My response was "Well, it's
*really* a pointer anyways, so what does it matter?" Now that I think
about this, I guess you should always pass by reference because you may
not always know if something is represented as a pointer. Is this the
reason? I have done more C than C++ so by nature I tend to focus on
pointers :)
The reason that passing a reference to a struct as opposed to a pointer
to a struct is that the pointer may be NULL (and you'd have to check
that in the called function). The usual `rule' is: pass by reference
when you can, pass a pointer when you must.

Why don't you post a (somewhat) more realistic snippet of code? That
would greatly enhance the possibility of providing a meaningful explanation.

HTH,
--ag
 
M

Mike

Alf said:
* Mike:

With a pointer you're saying: "I'm supporting a null-pointer argument".

With a reference you're saying: "This won't ever be a null-pointer".

I understand. But beneath the language isn't a reference just a pointer?
For example, passing a pointer by reference is equivalent (and probably
much unsafer) to double indirection. Or am I wrong? :) How does the
compiler guarantee that pass by reference is never undefined? Maybe I
just need to study this in more detail. Do you have any good references
on this topic?
Here the pointerness is hidden behind a name that doesn't signify
pointer, so it's possible your professor didn't even see the UB or the
null-pointer issue but just assumed you were passing a structure
(inefficiently) by value.
I think that's why he called me out... the possibility of passing by
value. Unfortunately, there's never an in-depth discussion on any
particular topic...

Thanks for the assistance.
 
M

Mike

Artie said:
Hiding a pointer type like this is, IMHO, ugly.

I agree -- I'd be doing things differently, but this is how it's taught,
unfortunately.
Do something?
Well, what you're planning to do here is *very* relevant!

What the function was doing is not relevant to how values are passed to
the function. "t" is a pointer to type "struct person," so you're
obviously passing a pointer. That's how I chose to pass it because I had
knowledge that "t" would be a pointer. But, the professor would have
preferred to see a function prototype of:

void somefunc(StructType& t);

I thougth that would be similar to double indirection, i.e. in terms of C:

void somefunc(StructType *t); // "t" is already a pointer...
As stated here, you're passing an unitialized pointer to a function
returning void. What could you *possibly* be doing?

Sorry about that. I didn't give fully working code as an example, so it
wasn't meant to be compiled and ran. Obviously it will cause a problem,
but I didn't want to focus on *what* the program is doing. I wanted to
focus on *how* arguments are passed by reference vs. pointer assuming
that variables had defined values.
Why don't you post a (somewhat) more realistic snippet of code? That
would greatly enhance the possibility of providing a meaningful
explanation.

Ok, I'll do that. I'll reply to my original post with something more
meaningful.
HTH,
--ag

Thanks.
 
M

Mike

Mike said:
Consider the following code:

"""
struct person {
char *name;
int age;
};

typedef struct person* StructType;

/* Think I got that syntax right above... :) */

void somefunc(StructType t)
{
// do something
}

int main()
{
StructType st;
somefunc(st);
}
"""

My professor called me out on my invocation of somefunc() by saying that
I should be passing by reference instead. My response was "Well, it's
*really* a pointer anyways, so what does it matter?" Now that I think
about this, I guess you should always pass by reference because you may
not always know if something is represented as a pointer. Is this the
reason? I have done more C than C++ so by nature I tend to focus on
pointers :)

Thanks.

Mike

Here's a more meaningful snippet of code.

"""
struct person {
char *name;
int age;
};

typedef struct person* StructType;

/* Think I got that syntax right above... :) */

void somefunc(StructType t)
{
// do something
}

void somefunc2(StructType& t)
{
// do something here, too.
}

int main()
{
// Yes, I know this isn't the best name...
StructType st = new person;
StructType st2 = NULL;

// passing "st" by pointer.
somefunc(st);

// passing "st2" by reference, which
// already is a NULL pointer. So, how does
// pass-by-reference become safer if "st2" is NULL?
// Won't the function see a NULL pointer regardless
// of how it was passed?
somefunc2(st2);

delete st;
}
"""

See my comments inline with the code.

Thanks.
 
A

Alf P. Steinbach

* Mike:
I understand. But beneath the language isn't a reference just a pointer?

As practical matter a reference T& is very much like a pointer T*const,
and the compiler can do much of the same kinds of optimizations.

But the language does not specify what a reference is beneath language.

Viewing a reference as a pointer in disguise is just a practical
conceptual picture, useful for understanding things and for debugging.

For example, passing a pointer by reference is equivalent (and probably
much unsafer) to double indirection. Or am I wrong? :)

Generally the reference is much safer.

How does the
compiler guarantee that pass by reference is never undefined?

It does not; that's your job. However, a quality compiler can help by
providing useful warnings here and there. But in the end it must assume
that you know what you're doing.

Maybe I
just need to study this in more detail. Do you have any good references
on this topic?

Nope, but you can try the FAQ, your nearest text-book, and
 
T

Thomas Tutone

Mike said:
I understand. But beneath the language isn't a reference just a pointer?
For example, passing a pointer by reference is equivalent (and probably
much unsafer) to double indirection. Or am I wrong? :)

It's not "unsafer," but the syntax does get a bit ugly.
How does the
compiler guarantee that pass by reference is never undefined? Maybe I
just need to study this in more detail. Do you have any good references
on this topic?

The FAQ:

http://www.parashift.com/c++-faq-lite/references.html

References may often be implemented as a const pointer. They may also
be optimized away (and for all I know, perhaps so may const pointers),
but that's an implementation detail.

Best regards,

Tom
 
M

Mike

Alf said:
It does not; that's your job. However, a quality compiler can help by
providing useful warnings here and there. But in the end it must assume
that you know what you're doing.

Ok, that clarifies my question in my most recent post with the clarified
example. I thought you were implying that passing by reference
automatically imposed some type of checking. :)

Nope, but you can try the FAQ, your nearest text-book, and
<url: http://home.no.net/dubjai/win32cpptut/special/pointers/ch_01.pdf>.

Thanks, I'll take a look at that.
 
M

Mike

Thomas said:
It's not "unsafer," but the syntax does get a bit ugly.

I'd rather much deal with references than pointers, especially with
double/triple indirection :)
The FAQ:

http://www.parashift.com/c++-faq-lite/references.html

References may often be implemented as a const pointer. They may also
be optimized away (and for all I know, perhaps so may const pointers),
but that's an implementation detail.

Thanks for the tip. Sometime in the near future I hope to take a
compiler class. I'm sure I'll learn more about implementation then...
 
H

Howard

Mike said:
Here's a more meaningful snippet of code.

"""
struct person {
char *name;
int age;
};

typedef struct person* StructType;

/* Think I got that syntax right above... :) */

void somefunc(StructType t)
{
// do something
}

void somefunc2(StructType& t)
{
// do something here, too.
}

int main()
{
// Yes, I know this isn't the best name...
StructType st = new person;
StructType st2 = NULL;

// passing "st" by pointer.
somefunc(st);

// passing "st2" by reference, which
// already is a NULL pointer. So, how does
// pass-by-reference become safer if "st2" is NULL?
// Won't the function see a NULL pointer regardless
// of how it was passed?
somefunc2(st2);

delete st;
}
"""

See my comments inline with the code.

I think everyone got a little confused here about what you were talking
about. If your examples here illustrate the problem, then it's not a matter
of passing by pointer versus passing by reference (as has been discussed
here), it's a matter of passing a pointer by value versus a pointer by
reference.

The difference is the same as with any other type: if you want to modify the
value (of the pointer st2, in this example), then you need to pass it (the
pointer) by reference (or else by via pointer-to-pointer).

If you pass the pointer by value, and inside the function you modify the
pointer (such as by assigning the result of "new" to it), then you're only
modifying the local _copy_ of the pointer, not the pointer itself.

So, it all depends upon what you are doing _inside_ the called function, as
to whether you want to pass the pointer by value (as in somefunc()) or by
reference (as in somefunc2()).

-Howard
 
B

Ben Pope

Mike said:
Here's a more meaningful snippet of code.

"""
struct person {
char *name;
int age;
};

typedef struct person* StructType;

/* Think I got that syntax right above... :) */

typedef person* StructType;

Will suffice. A struct does not need to be qualified with that keyword
in C++, only in C.
void somefunc(StructType t)
{
// do something
}

void somefunc2(StructType& t)
{
// do something here, too.
}

int main()
{
// Yes, I know this isn't the best name...
StructType st = new person;
StructType st2 = NULL;

// passing "st" by pointer.
somefunc(st);

// passing "st2" by reference, which
// already is a NULL pointer. So, how does
// pass-by-reference become safer if "st2" is NULL?
// Won't the function see a NULL pointer regardless
// of how it was passed?
somefunc2(st2);

delete st;
}
"""

See my comments inline with the code.

You have gained nothing because you still have the pointer there.
Consider this:

void someFunc3(person& t) {
// Now t cannot be null
}

I would not recommend hiding the pointer behind a typedef, pointers
cause enough trouble when they're visible an obvious. When they're
hidden, it's even more of a pain to find the problem.

Ben Pope
 

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
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top