Don't pass by reference to non-const?

S

Sousuke

Stroustrup advocates this guideline as well in "The C++ Programming
Language." I don't particularly care for it myself.

Thanks. Could you tell me the section?
My own guideline is to use pointers as arguments if the object pointed
to has to live longer than the function being called (or if the argument
is a C array.) For example, if the function is storing the object
pointed to somewhere for later use.

Or if the pointed-to type is an abstract class, I think.
 
A

Alf P. Steinbach

* Sousuke:
I'm having doubts about the validity of the following guideline:

http://google-styleguide.googlecode...owone=Reference_Arguments#Reference_Arguments

For some reason I haven't noticed whether this is generally followed.
Is it? Or is it just something made up at Google? What do you think of
it?

Please quote the guideline you refer to.

<quote>
Reference Arguments

All parameters passed by reference must be labeled const.

Definition: In C, if a function needs to modify a variable, the parameter must
use a pointer, eg int foo(int *pval). In C++, the function can alternatively
declare a reference parameter: int foo(int &val).

Pros: Defining a parameter as reference avoids ugly code like (*pval)++.
Necessary for some applications like copy constructors. Makes it clear, unlike
with pointers, that NULL is not a possible value.

Cons: References can be confusing, as they have value syntax but pointer semantics.

Decision:

Within function parameter lists all references must be const:

void Foo(const string &in, string *out);

In fact it is a very strong convention in Google code that input arguments are
values or const references while output arguments are pointers. Input parameters
may be const pointers, but we never allow non-const reference parameters.

One case when you might want an input parameter to be a const pointer is if you
want to emphasize that the argument is not copied, so it must exist for the
lifetime of the object; it is usually best to document this in comments as well.
STL adapters such as bind2nd and mem_fun do not permit reference parameters, so
you must declare functions with pointer parameters in these cases, too.
</quote>


I.e. Google would design std::getline with pointer argument.

It sounds political.

From a non-political perspective it's pretty stupid since it requires extra
notation and requires unnecessary bug-vectors, both something you would
absolutely not want in the code, but presumably that "decision" made sense in
some workplace politics, something with not too disturbing consequences that
some group was very opposed to but had to accept; you're the boss, man.


Cheers,

- Alf (telepathic circuit engaged)
 
I

Ian Collins

Stroustrup advocates this guideline as well in "The C++ Programming
Language." I don't particularly care for it myself.

My own guideline is to use pointers as arguments if the object pointed
to has to live longer than the function being called (or if the argument
is a C array.) For example, if the function is storing the object
pointed to somewhere for later use.

Um, surely any object that gets passed by non-const reference lives
longer the the function being called?
 
S

Sousuke


Maybe I'm just confused because the code I'm currently working on
deals heavily with reference-counted pointers to abstract classes (so
they're always dynamically allocated), so it makes sense to pass them
around as pointers.
 
B

Balog Pal

Sousuke said:
I'm having doubts about the validity of the following guideline:

http://google-styleguide.googlecode...owone=Reference_Arguments#Reference_Arguments

For some reason I haven't noticed whether this is generally followed.
Is it? Or is it just something made up at Google? What do you think of
it?

As a general point, stay away from google's style guide. It has many
questionable or outright WTF points. (At least it did a year ago, when I
twitlisted it.)

Sure you can find a set of really good guides. When in doubt look at
Sutter/Alexandrescu book and its references.
 
J

James Kanze

On 05/ 2/10 09:30 AM, Sousuke wrote:
I haven't seen it used and I don't like it. It appears
inconsistent, mixing reference and pointer parameters for no
good reason.

Yes and no. The logic is that in arguments are references, out
and inout pointers. This has two advantages:

-- It requires explicit action at the call site in order to
pass an out argument; you can see immediately that the
argument might change.

-- It ensures that even if you currently compile with a
compiler that doesn't enforce the rule forbidding
initializing a non-const reference with an rvalue (VC++, for
example), your code will compile with more "correct"
compilers: all compilers require an lvalue in order to use
the (built-in) & operator.

Neither are "killer" arguments, and certainly a lot of other
conventions are possible. In the end, you only have two
choices, and there are far more than one binary information that
might be useful to indicate. Still, way, way back, this was the
convention I preferred. I'd gotten out of it, because the
places I'd worked in used other conventions, but the circle has
turned, and where I work now uses it (and used it before I got
there).
 
J

James Kanze

Stroustrup advocates this guideline as well in "The C++
Programming Language." I don't particularly care for it
myself.
My own guideline is to use pointers as arguments if the object
pointed to has to live longer than the function being called
(or if the argument is a C array.) For example, if the
function is storing the object pointed to somewhere for later
use.

That's another convention. Probably the most common. (At
least, it seemed to be when I did a small survey of the issue.
About 15 years ago.) A third is to use a pointer if a null
pointer is conceivably valid, a reference otherwise.
I use const reference as an optimization of passing by
value.

The issue here isn't const reference as an optimization of pass
by value. It's non-const referenced vs. non-const pointer for
out (and inout) parameters.

Note that regardless of the convention otherwise: if the <op>=
(and prefixed ++ and --) operators aren't members, then their
first (only) argument must be a non-const reference. (And
although I generally make them members, there are also good
arguments for a convention which makes them free functions.)
 
J

James Kanze

* Sousuke:

[...]
I.e. Google would design std::getline with pointer argument.
It sounds political.

Obviously. When there are several different, mutually exclusive
possibilities, all of which have valid technical arguments in
their favor, the final choice will be political. Any choice
concerning when to use references and when to use pointers in a
function interface is at least partially political.
From a non-political perspective it's pretty stupid since it
requires extra notation and requires unnecessary bug-vectors,

The "extra" notation is redundancy. Redundancy which makes the
code more readable and more easily understandable. (The
alternatives have other advantages, so in the end, which one you
choose is a "political" decision. None of the usual choices is
perfect, and none provides all of the possible advantages.)

And what do you mean by "bug-vectors"? I'm not familiar with
the term.
 
A

Alf P. Steinbach

* Sousuke:
[...]
I.e. Google would design std::getline with pointer argument.
It sounds political.

Obviously. When there are several different, mutually exclusive
possibilities, all of which have valid technical arguments in
their favor, the final choice will be political. Any choice
concerning when to use references and when to use pointers in a
function interface is at least partially political.
From a non-political perspective it's pretty stupid since it
requires extra notation and requires unnecessary bug-vectors,

The "extra" notation is redundancy. Redundancy which makes the
code more readable and more easily understandable. (The
alternatives have other advantages, so in the end, which one you
choose is a "political" decision. None of the usual choices is
perfect, and none provides all of the possible advantages.)

And what do you mean by "bug-vectors"? I'm not familiar with
the term.

E.g. a disease vector is a way the disease can enter your body or a population.

A bug vector is a way a bug can enter a program.

Such as inadvertently passing null-pointers to routines that don't expect them,
when that is made easy to do by the routine signature.


Cheers,

- Alf
 
I

Ian Collins

Yes and no. The logic is that in arguments are references, out
and inout pointers. This has two advantages:

-- It requires explicit action at the call site in order to
pass an out argument; you can see immediately that the
argument might change.

-- It ensures that even if you currently compile with a
compiler that doesn't enforce the rule forbidding
initializing a non-const reference with an rvalue (VC++, for
example), your code will compile with more "correct"
compilers: all compilers require an lvalue in order to use
the (built-in)& operator.

Neither are "killer" arguments, and certainly a lot of other
conventions are possible. In the end, you only have two
choices, and there are far more than one binary information that
might be useful to indicate. Still, way, way back, this was the
convention I preferred. I'd gotten out of it, because the
places I'd worked in used other conventions, but the circle has
turned, and where I work now uses it (and used it before I got
there).

I guess those are sound arguments. But I find I seldom use out
parameters. I something has to be returned, return it!
 
B

Balog Pal

Ian Collins said:
I guess those are sound arguments. But I find I seldom use out
parameters. I something has to be returned, return it!

Also they goe against the naturals. Reference means there is always an
object. Pointer can be NULL so that implies an optional thing.

Then again, the very lack of const in the signature documents that it is an
out parameter. With poiter or reference all the same.

In C++ code I try to limit pointer usage to bare minimum. Watering that up
is not good.

OTOH, I agree with the latter observation. In the early times I used to pass
an empty object frequently to 'fill' in a function instead of returning it.
retutning vectors of stuff looked bad. But I left it behind eventually. So
out params are indeed rare in my code, possibly limited to cases when I have
multiple items that are chosen not to be tupled. That still leaves the
input params for nonconst refs.
 
J

James Kanze

On 05/ 2/10 09:45 PM, James Kanze wrote:

[...]
I guess those are sound arguments. But I find I seldom use out
parameters. I something has to be returned, return it!

In general, I agree, and out parameters should be fairly rare.
There are some exceptions, however: anyone who's written a large
application in Java will certainly be aware of them (since Java
has no support for out parameters what so ever). And sometimes,
performance issues raise their ugly head---in my current work,
we do use out parameters of things like std::vector<double>,
because returning a vector with a couple of thousand elements
was too slow.
 
J

James Kanze

When op<< is a free function, the first argument is a
non-const reference. I guess Google is saying that op<< cannot
be defined for any user type, or are they demanding that the
calling code must look like &cout << myObject;

Yes. Operator overloading is a special case. They don't seem
to make an explicit exception, but presumably, it would be
allowed. (Operator overloading is widely abused, and should be
limited much more than it normally is. But the << is an
established use. And for things like +=, as I said, there are
some very good arguments for making it a non-member. Even if I
don't do so.)
 
J

James Kanze

Well another of their guidelines is:
"Do not overload operators except in rare, special circumstances."
So I suspect the issue doesn't arise for them too often.

That's a good rule in general, but there are some obvious
exceptions: any class with value semantics should overload
operator=, for example, and any class which models a numeric
value should probably overload the appropriate mathematical
operators. Throw in operator* and operator-> for smart
pointers, and operator[] for "arrays", and IMHO, that about
covers it. (The use of ++ to advance an iterator is debatable.)
 
J

James Kanze

On 02.05.2010 12:01, * James Kanze:

[..]
E.g. a disease vector is a way the disease can enter your body
or a population.
A bug vector is a way a bug can enter a program.

OK. For some reason, I interpreted "vector" in its C++ meaning.
Such as inadvertently passing null-pointers to routines that
don't expect them, when that is made easy to do by the routine
signature.

Yes. That's an argument for a different convention. As I said,
there are valid arguments for several different conventions.
 
B

Balog Pal

James Kanze said:
And sometimes,
performance issues raise their ugly head---in my current work,
we do use out parameters of things like std::vector<double>,
because returning a vector with a couple of thousand elements
was too slow.

You mean you had a situation wanting performance yet you used a compiler
that did so poor job on optimization that retutning a vector was actually
slower than passing in an empty one by reference?
 
I

Ian Collins

You mean you had a situation wanting performance yet you used a compiler
that did so poor job on optimization that retutning a vector was
actually slower than passing in an empty one by reference?

I was about to post the same comment (until some prawn in a digger hit
our power cable!). I ran a quick test and found passing by reference
slower than returning a vector of 10000 doubles. I had expected them to
be about the same.
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top