473,397 Members | 1,960 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,397 software developers and data experts.

Reference parameters

I have been encouraged by someone else to use a reference rather than a
pointer as an "out" parameter to a function, eg.

void doStuff(Thing &out1, Thing &out2)

as opposed to:

void doStuff(Thing *out1, Thing *out2)

The issue I have with this is that when the function is called, you cannot
tell that the value is being modified:

doStuff(thing1, thing2);

This is much less obvious than:

doStuff(&thing1, &thing2);

The only disadvantages I can think of with using pointers here are:

- a NULL pointer could be passed in by mistake
- the body of doStuff() is slightly more verbose (*out1 instead of out1, ->
instead of ".")
- I suppose the pointer could be accidentally reassigned, incremented,
deleted, etc

I would rank readability and clarity in the use of functions as more
important than any of these things (since most of a program's lifetime is
usually maintenance, not necessarily by the original writer). The friend who
was encouraging the use of references said that it was "more C++ish", but
that by itself isn't a very good argument ...

Any comments ?

David F

PS. I am aware of
http://www.parashift.com/c++-faq-lit...s.html#faq-8.6 ...
Jul 22 '05 #1
15 1799
On Sun, 30 Nov 2003 17:54:29 +1100, "David Fisher"
<no****@nospam.nospam.nospam> wrote:
I have been encouraged by someone else to use a reference rather than a
pointer as an "out" parameter to a function, eg.

void doStuff(Thing &out1, Thing &out2)

as opposed to:

void doStuff(Thing *out1, Thing *out2)

The issue I have with this is that when the function is called, you cannot
tell that the value is being modified:

doStuff(thing1, thing2);

This is much less obvious than:

doStuff(&thing1, &thing2);

The only disadvantages I can think of with using pointers here are:

- a NULL pointer could be passed in by mistake
- the body of doStuff() is slightly more verbose (*out1 instead of out1, ->
instead of ".")
- I suppose the pointer could be accidentally reassigned, incremented,
deleted, etc

I would rank readability and clarity in the use of functions as more
important than any of these things (since most of a program's lifetime is
usually maintenance, not necessarily by the original writer). The friend who
was encouraging the use of references said that it was "more C++ish", but
that by itself isn't a very good argument ...

Any comments ?


Personally, I prefer to use pointers for out parameters. For everything
else I use const references. The advantage of being able to tell
instantly if something passed to a function could be modified outweighs
the disadvantages I've seen.

I don't buy the argument that pointer arguments are inherently unsafe.
If the caller is always taking the address of existing variables, there
will be no NULL pointers to worry about. On the other hand if the caller
only has pointers at its disposal, you're no better off if you take a
reference. A dereferenced NULL pointer is as bad as a NULL pointer.
Asserting that a pointer argument is non-NULL is natural, and is the
first thing any developer would do in a function that takes pointers. If
you take a reference, you can be passed NULL-references just as easily,
but most developers typically would not check for that.

Sure, it's the caller's responsibility to check the validity of the
arguments passed to the function, but that's true for both cases.

--
Be seeing you.
Jul 22 '05 #2
David Fisher escribió:
I have been encouraged by someone else to use a reference rather than a
pointer as an "out" parameter to a function, eg.

void doStuff(Thing &out1, Thing &out2)

as opposed to:

void doStuff(Thing *out1, Thing *out2)

The issue I have with this is that when the function is called, you cannot
tell that the value is being modified:

doStuff(thing1, thing2);

This is much less obvious than:

doStuff(&thing1, &thing2);


Then rename the function:

evaluateThings (thing1, thing2);

Regards.
Jul 22 '05 #3
On Sun, 30 Nov 2003 01:25:35 -0600, Thore Karlsen <si*@6581.com> wrote:
Personally, I prefer to use pointers for out parameters. For everything
else I use const references.
Check out Andrei Alexandrescu's "Modern C++ Design" for automatic choice
between "by value" and "by const ref".

The advantage of being able to tell
instantly if something passed to a function could be modified outweighs
the disadvantages I've seen.
Unfortunately that advantage requires (1) that no argument contains a
reference or pointer, which restricts the advantage to a very small subset
of functions, (2) familiarity with the specific function or set of functions
that it belongs to, where presumably it's less of a real advantage, to the
degree that is any advantage, (3) for the case of a familiar set of
functions, that they all adhere strictly to the non-ref convention, not a
single unknown case of pass-by-reference, (4) that the function or functions
are sufficiently badly designed that there can be any doubt about their
effects (i.e. they're presumably not your functions), and (5) that you can
always see from the calling code whether the arguments are pointers or not.

With all these restrictions it seems to me to be a very dubious advantage.

There's no need to invoke such an advantage to justify using pointers.
I don't buy the argument that pointer arguments are inherently unsafe.
If the caller is always taking the address of existing variables, there
will be no NULL pointers to worry about. On the other hand if the caller
only has pointers at its disposal, you're no better off if you take a
reference. A dereferenced NULL pointer is as bad as a NULL pointer.
Asserting that a pointer argument is non-NULL is natural, and is the
first thing any developer would do in a function that takes pointers. If
you take a reference, you can be passed NULL-references just as easily,
but most developers typically would not check for that.
Because checking for NULL-pointers in both caller and callee is redundant;
furthermore, because checking that the address of a reference argument
is non-NULL depends on a formally undefined effect and so is at best false
security (which is dangerous); and most of all, because a reference argument
is a contractual obligation on the caller; see below.

Sure, it's the caller's responsibility to check the validity of the
arguments passed to the function, but that's true for both cases.


Check out the Design By Contract (DBC) philosophy, e.g. as described by
Betrand Meyer himself in "Object Oriented Software Construction". The crux
of that philosophy is to clearly place requirements and responsibilities on
the caller (client code) and the callee (routine) so as to both avoid
redundancy and increase clarity. Some C++ programmers use reference arguments
to express that an argument cannot be NULL (which stems from the language
definition, and so is an absolute requirement on the caller), and pointer
arguments to express that those arguments may be NULL (which is just a vague
and context-dependent convention, must be checked if it's not clear).

Jul 22 '05 #4
> The issue I have with this is that when the function is called, you cannot
tell that the value is being modified:

doStuff(thing1, thing2);

This is much less obvious than:

doStuff(&thing1, &thing2);

The only disadvantages I can think of with using pointers here are:

- a NULL pointer could be passed in by mistake
- the body of doStuff() is slightly more verbose (*out1 instead of out1, -> instead of ".")
- I suppose the pointer could be accidentally reassigned, incremented,
deleted, etc


Would you be willing to have to write

std::cin >> &x;

instead of

std::cin >> x;

?
Jul 22 '05 #5
On Sun, 30 Nov 2003 12:08:46 GMT, al***@start.no (Alf P. Steinbach)
wrote:
Personally, I prefer to use pointers for out parameters. For everything
else I use const references.
Check out Andrei Alexandrescu's "Modern C++ Design" for automatic choice
between "by value" and "by const ref".
"Everything" was too strong, and yes, I've read that and follow it.
The advantage of being able to tell
instantly if something passed to a function could be modified outweighs
the disadvantages I've seen. Unfortunately that advantage requires (1) that no argument contains a
reference or pointer, which restricts the advantage to a very small subset
of functions, (2) familiarity with the specific function or set of functions
that it belongs to, where presumably it's less of a real advantage, to the
degree that is any advantage, (3) for the case of a familiar set of
functions, that they all adhere strictly to the non-ref convention, not a
single unknown case of pass-by-reference, (4) that the function or functions
are sufficiently badly designed that there can be any doubt about their
effects (i.e. they're presumably not your functions), and (5) that you can
always see from the calling code whether the arguments are pointers or not.

With all these restrictions it seems to me to be a very dubious advantage.

There's no need to invoke such an advantage to justify using pointers.
I don't agree that pointers are inherently bad and their use needs to be
justified.

I prefer readability to purism, real life advantages (for me) to
theoretical disadvantages. In short, it works for me. I've tried the
alternative, and I found it to be less clear.
I don't buy the argument that pointer arguments are inherently unsafe.
If the caller is always taking the address of existing variables, there
will be no NULL pointers to worry about. On the other hand if the caller
only has pointers at its disposal, you're no better off if you take a
reference. A dereferenced NULL pointer is as bad as a NULL pointer.
Asserting that a pointer argument is non-NULL is natural, and is the
first thing any developer would do in a function that takes pointers. If
you take a reference, you can be passed NULL-references just as easily,
but most developers typically would not check for that. Because checking for NULL-pointers in both caller and callee is redundant;
furthermore, because checking that the address of a reference argument
is non-NULL depends on a formally undefined effect and so is at best false
security (which is dangerous); and most of all, because a reference argument
is a contractual obligation on the caller; see below.
Yes. And so nobody checks. But that doesn't mean NULL references don't
happen. And when they do happen they are typically harder to catch
because there's no assert to check for them.
Sure, it's the caller's responsibility to check the validity of the
arguments passed to the function, but that's true for both cases.

Check out the Design By Contract (DBC) philosophy, e.g. as described by
Betrand Meyer himself in "Object Oriented Software Construction". The crux
of that philosophy is to clearly place requirements and responsibilities on
the caller (client code) and the callee (routine) so as to both avoid
redundancy and increase clarity. Some C++ programmers use reference arguments
to express that an argument cannot be NULL (which stems from the language
definition, and so is an absolute requirement on the caller), and pointer
arguments to express that those arguments may be NULL (which is just a vague
and context-dependent convention, must be checked if it's not clear).


That is one convention. Unfortunately the real world does not follow it.
Unless it is explicitly documented that a pointer argument can be NULL,
assume it cannot be.

--
Be seeing you.
Jul 22 '05 #6
On Sun, 30 Nov 2003 11:08:55 -0600, Thore Karlsen <si*@6581.com> wrote:
On Sun, 30 Nov 2003 12:08:46 GMT, al***@start.no (Alf P. Steinbach)
wrote:
On Sun, 30 Nov 2003 01:25:35 -0600, Thore Karlsen <si*@6581.com> wrote:
Sure, it's the caller's responsibility to check the validity of the
arguments passed to the function, but that's true for both cases.

Check out the Design By Contract (DBC) philosophy, e.g. as described by
Betrand Meyer himself in "Object Oriented Software Construction". The crux
of that philosophy is to clearly place requirements and responsibilities on
the caller (client code) and the callee (routine) so as to both avoid
redundancy and increase clarity. Some C++ programmers use reference arguments
to express that an argument cannot be NULL (which stems from the language
definition, and so is an absolute requirement on the caller), and pointer
arguments to express that those arguments may be NULL (which is just a vague
and context-dependent convention, must be checked if it's not clear).


That is one convention. Unfortunately the real world does not follow it.


<meta>
That response feels uncannily like my first encounters with really bad
low-level management in one of the world's largest consulting firms, where
I worked for some years. It's not a good idea to pick up response-patterns
from bad low-level managers. Instead, try to emulate the good ones, if any.
Below I try to treat the statement as a technical or at least factual/belief
statement. As you can see there is much room also for technical interpretation.
</meta>

In order of my sentences:

A) Do you think DBC is not described by Bertrand Meyer in the mentioned book?

B) Do you think the description of the crux of that philosophy is incorrectly
stated?

C) Do you think it's untrue that some C++ programmers use reference arguments
to express that an argument cannot be NULL?

D) Do you think checking for NULL address of a reference argument is a
well-defined operation?

E) Do you think it's untrue that some C++ programmers use pointers to indicate
that arguments can be NULL?

F) Do you think that convention (E) need not be checked if it's not clear?

G) And/or, do you think that programmers do not use or should better not use
the DBC philosophy?

Jul 22 '05 #7
In article <0x******************@nasal.pacific.net.au>,
David Fisher <no****@nospam.nospam.nospam> wrote:
I have been encouraged by someone else to use a reference rather than a
pointer as an "out" parameter to a function, eg.

void doStuff(Thing &out1, Thing &out2)

as opposed to:

void doStuff(Thing *out1, Thing *out2)


[snip pro and con arguments]

In this context, using pointers versus references is pretty much a
religious-type argument. I personally prefer to use references unless I
absolutely need to use pointers, but I'm not going to shoot someone who
prefers otherwise. I'd just as soon not have to maintain their code,
though, just as I expect pointer-believers would just as soon not have to
maintain mine. ;-)

--
Jon Bell <jt*******@presby.edu> Presbyterian College
Dept. of Physics and Computer Science Clinton, South Carolina USA
Jul 22 '05 #8
"Andrew Koenig" <ar*@acm.org> wrote:
Would you be willing to have to write

std::cin >> &x;

instead of

std::cin >> x;


No, because in this case it is obvious that x is going to be modified ...
Just concerned about readability, that's all.

BTW does anyone have a convention for marking in, out and in/out parameters
? I kind of like the IDL file convention which actually has keywords like
"in" and "out" before parameters, eg. (real example; "boolean" is IDL for
"bool"):

boolean getSATCVessel(in string satcId, out SpecialVessel vessel)

and I have seen a coding standard which requires a comment for each
parameter:

void fred(
int n // in - <description>
int *m // in/out - <description>
);

I guess most argument types are self describing, though (T and const T& are
"in" paremeters, etc) ...

David F
Jul 22 '05 #9

"David Fisher" <no****@nospam.nospam.nospam> wrote in message
news:0x******************@nasal.pacific.net.au...
I have been encouraged by someone else to use a reference rather than a
pointer as an "out" parameter to a function, eg.

void doStuff(Thing &out1, Thing &out2)

as opposed to:

void doStuff(Thing *out1, Thing *out2)

The issue I have with this is that when the function is called, you cannot
tell that the value is being modified:

doStuff(thing1, thing2);

This is much less obvious than:

doStuff(&thing1, &thing2);
This is a well-known concern, but also one that tends to go away with more
experience. Looking at the function prototype should tell you all you need
to know. A comment before call to doStuff can certainly clarify the purpose
of doStuff, at least part of which is to change the value of the parameters.
The only disadvantages I can think of with using pointers here are:

- a NULL pointer could be passed in by mistake
- the body of doStuff() is slightly more verbose (*out1 instead of out1, -> instead of ".")
- I suppose the pointer could be accidentally reassigned, incremented,
deleted, etc

I would rank readability and clarity in the use of functions as more
important than any of these things (since most of a program's lifetime is
usually maintenance, not necessarily by the original writer). The friend who was encouraging the use of references said that it was "more C++ish", but
that by itself isn't a very good argument ...


Rather than calling it more C++ish, I'd say it's actually more readable and
clear, and less error prone than using pointers. Why use all that nasty
pointer syntax inside the doStuff function, when simply using the parameter
name naked is much more clear?
Jul 22 '05 #10

"Thore Karlsen" <si*@6581.com> wrote in message
news:pa********************************@4ax.com...

I don't buy the argument that pointer arguments are inherently unsafe.
If the caller is always taking the address of existing variables, there
will be no NULL pointers to worry about.


Right. And if the developer never makes any mistakes, there will be no bugs
in the world.
Jul 22 '05 #11

"David Fisher" <no****@nospam.nospam.nospam> wrote in message
news:nr******************@nasal.pacific.net.au...

BTW does anyone have a convention for marking in, out and in/out parameters ? I kind of like the IDL file convention which actually has keywords like
"in" and "out" before parameters, eg. (real example; "boolean" is IDL for
"bool"):

boolean getSATCVessel(in string satcId, out SpecialVessel vessel)

and I have seen a coding standard which requires a comment for each
parameter:

void fred(
int n // in - <description>
int *m // in/out - <description>
);


That wouldn't solve the OP's concern though, which was in regard to the
calling syntax, not the function definition itself.
Jul 22 '05 #12
"jeffc" <no****@nowhere.com> wrote in message
news:3f********@news1.prserv.net...

"David Fisher" <no****@nospam.nospam.nospam> wrote in message
news:0x******************@nasal.pacific.net.au...
I have been encouraged by someone else to use a reference rather than a
pointer as an "out" parameter to a function, eg.

void doStuff(Thing &out1, Thing &out2)

as opposed to:

void doStuff(Thing *out1, Thing *out2)

The issue I have with this is that when the function is called, you cannot tell that the value is being modified:

doStuff(thing1, thing2);

This is much less obvious than:

doStuff(&thing1, &thing2);
This is a well-known concern, but also one that tends to go away with more
experience. Looking at the function prototype should tell you all you

need to know. A comment before call to doStuff can certainly clarify the purpose of doStuff, at least part of which is to change the value of the

parameters.

Well, what you know when looking at a function call passing an argument is
that it might be modified.
If you want guarantees that it won't be, use const.
Yeah, the prototype is your friend here, but it might often be hidden in an
included header. Indeed, what's to stop a coder of a third party library
(where all you know is to call the function) changing an implementation to
reference and neglecting to inform you (through documentation -- you
remember documentation?). The lack of really good documentation system is
one of C++'s worst faults as far as I'm concerned. (Now, Javadocs, there's a
work of art.)

Somebody fill me in: can arrays be passed to a reference or are they always
pointers?
--
Gary
Jul 22 '05 #13

"Gary Labowitz" <gl*******@comcast.net> wrote in message
news:1O********************@comcast.com...
Yeah, the prototype is your friend here, but it might often be hidden in an included header. Indeed, what's to stop a coder of a third party library
(where all you know is to call the function) changing an implementation to
reference and neglecting to inform you (through documentation -- you
remember documentation?).


I don't follow you. What do you mean by "hidden in an included header"?
It's not true that "all you know is to call the function". You must also
have the header, and thus the prototype. Certainly, third party code is
going to be documented, at the very least with the header itself, and it's
essential for any programmer to look at the prototypes before making any
calls.
Jul 22 '05 #14
"jeffc" <no****@nowhere.com> wrote in message
news:3f********@news1.prserv.net...

"Gary Labowitz" <gl*******@comcast.net> wrote in message
news:1O********************@comcast.com...
Yeah, the prototype is your friend here, but it might often be hidden in

an
included header. Indeed, what's to stop a coder of a third party library
(where all you know is to call the function) changing an implementation to reference and neglecting to inform you (through documentation -- you
remember documentation?).


I don't follow you. What do you mean by "hidden in an included header"?


I was suggesting that most people don't bother printing the header when they
include it.
Some of them are fairly difficult to read, in addition to all that. I didn't
mean that the header information wasn't available.
--
Gary
Jul 22 '05 #15

"jeffc" <no****@nowhere.com> wrote:
Rather than calling it more C++ish, I'd say it's actually more readable and clear, and less error prone than using pointers. Why use all that nasty
pointer syntax inside the doStuff function, when simply using the parameter name naked is much more clear?


One way around this would be to use a local reference for readability:

void fred(int *x_ptr)
{
assert(x_ptr != NULL);
int &x = *x_ptr;

... do something with x ...
}

That way the caller can say fred(&x) and the function can still be readable,
too.

I learnt Pascal before C/C++, and it had a useful "with" statement which let
you reference fields of a record (struct) in the next block without needing
to use the full name; using a local reference is a bit like that. I do this
using constant references when I don't want to write something out in full
each time:

const SomeStructType &s = someArrayOfArrays[n].someArrayOfStructs[m];

cout << s.field1 << ", " << s.field2;

David F
Jul 22 '05 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

110
by: Mr A | last post by:
Hi! I've been thinking about passing parameteras using references instead of pointers in order to emphasize that the parameter must be an object. Exemple: void func(Objec& object); //object...
39
by: Mike MacSween | last post by:
Just spent a happy 10 mins trying to understand a function I wrote sometime ago. Then remembered that arguments are passed by reference, by default. Does the fact that this slowed me down...
5
by: Javier Campos | last post by:
WARNING: This is an HTML post, for the sake of readability, if your client can see HTML posts, do it, it doesn't contain any script or virus :-) I can reformat a non-HTML post if you want me to (and...
5
by: Greg | last post by:
Hi, I have been unable to resolve this error message: Object Ref not set to an instance of an object. The issue is that I cannot determine which object reference is causing the problem. ...
7
by: Brett | last post by:
I'm not sure why I keep getting this error, "Object reference not set to an instance of an object". Private Function somefunction() as string Dim MyCurrentClass As New Class1 Try For i As...
0
by: webbsk | last post by:
I keep getting an exception when I call the DataAdapter Update method. I have been trying to figure out what is causing the null reference exception for this code for what seems like forever: ...
1
by: Kevin | last post by:
ASP.NET 2.0 I have code that updates a database from a number of textboxes on a web form. I've had to hard coded references to my web form textboxes. I'd like to know how I can reference them...
29
by: shuisheng | last post by:
Dear All, The problem of choosing pointer or reference is always confusing me. Would you please give me some suggestion on it. I appreciate your kind help. For example, I'd like to convert a...
13
by: Francois Appert | last post by:
This post was originally in the C# Corner site, but their server is down. I'd like to see if this group can answer. I program in C++ and am learning C#. The issue is: why should anybody...
275
by: Astley Le Jasper | last post by:
Sorry for the numpty question ... How do you find the reference name of an object? So if i have this bob = modulename.objectname() how do i find that the name is 'bob'
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.