473,322 Members | 1,755 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,322 software developers and data experts.

Pass-by-reference instead of pass-by-pointer = a bad idea?

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 must be an object

instead of

void func(Object* object); //object can be NULL

I belive that this is a good idea since , in the reference case, it's
clear that NULL is not an option. It's also clear that NULL is an
option when a pointer is expected (stating the obvious :-) ). The code
becomes somewhat more self-documenting.

Any comments on why this could be a bad idea or do you think it's just
a matter of taste?

/H
Jul 23 '05
110 9786
Stuart MacMartin wrote:
The point of this whole discussion seems to be whether it's way too
easy to pass a dereferenced null pointer to a parameter that is defined
as reference.
This is an error in the caller - but is it the responsibility of the
called function to catch this error?


And when passing by value? Is your resposability to ensure that the caller
never dereference a null pointer to pass the value?

I think it's not so esay, you must dereference it. Then, the responsability
is yours.

And in cases when for some reason is esay to make a mistake, you can just
write a wrapper that takes a pointer, make all checks desired and calls the
original function.

--
Salu2
Jul 23 '05 #51
Stuart MacMartin wrote:
You say:
BTW, my reading of the Standard suggests there is no need to check that
node
is not null before I try to dynamic_cast it. Does anybody disagree
with
that understanding?

My reply:
Yes, dynamic_cast will return 0 if passed 0.
But if this code is time-critical, don't do this from MFC.
dynamic_cast is a performance bottleneck.
It works by doing a whole pile of string compares.
(This is why our objects have virtual IsSpecificType methods that we
can invoke.)

Stuart


That sounds a whole lot like bad implementation more than any fundamental
problem with dynamic_cast. dynamic_cast should be doable with fairly
simple numeric based comparison. GCC compares the addresses of the type
strings. Oh my! That's a Java '=='. Don't tell anybody. :)
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #52
Julián Albo wrote:
Stuart MacMartin wrote:
The point of this whole discussion seems to be whether it's way too
easy to pass a dereferenced null pointer to a parameter that is defined
as reference.
This is an error in the caller - but is it the responsibility of the
called function to catch this error?


And when passing by value? Is your resposability to ensure that the caller
never dereference a null pointer to pass the value?

I think it's not so esay, you must dereference it. Then, the
responsability is yours.

And in cases when for some reason is esay to make a mistake, you can just
write a wrapper that takes a pointer, make all checks desired and calls
the original function.

If I allocate an object on the freestore, I have to keep a pointer to it if
I am to manage it, which I will certainly want to do. That means if I want
to use a reference, I have to initialize a reference using the pointer. If
it is polymorphic, I will likely want to dynamic_cast it somewhere down the
line. If I dynamic_cast a reference, I have to try/catch it, and branch
based on exception handling. That is bad design. Furthermore, we cannot
currently reseat a reference (though I believe the new move semantic
incorporates that ability). That means I have to be more carful about what
I do with a reference than I need to be with a pointer. For instance, I
cannot reuse a reference to successively handle a sequence of objects, as I
can with a pointer. I cannot have a container of references. It seems to
me the limitations of working with references are pretty widespread. IMO,
the best advantage a reference has over a pointer is the fact that (*ptr
[i] or worse (*ptr)() is ugly.

AFAIK, references were created to facilitate operator overloading, and they
seem best suited for that kind of a role.
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #53
Steven T. Hatton wrote:
If I allocate an object on the freestore, I have to keep a pointer to it
if I am to manage it, which I will certainly want to do. That means if I
want to use a reference, I have to initialize a reference using the
pointer. If it is polymorphic, I will likely want to dynamic_cast it
somewhere down the line. If I dynamic_cast a reference, I have to
try/catch it, and branch based on exception handling. That is bad design.
If you don't want to use dynamic_cast of references, just don't do it. Who
forces you do do that? You can dereference after casting and checking, for
example.
That means I have to be more carful about what I do with a reference than
I need to be with a pointer. For instance, I cannot reuse a reference to
successively handle a sequence of objects, as I can with a pointer.


Then use a pointer if you want. You are not forced to choose the party of
the pointers or the party of the references.

--
Salu2
Jul 23 '05 #54
In article <19*************************@posting.google.com> ,
Mr A <al**************@hotmail.com> wrote:
void func(Object* object); //object can be NULL
I think the reverse is the case: if the pointer can be NULL, the only
option is a pointer.

I prefer pass-by-ref simply because the syntax is easier ('.' instead
of '->' etc.).
Any comments on why this could be a bad idea or do you think it's
just a matter of taste?


Just because your signature is func(Object& obj), it won't prevent
others from passing in pointers:

Object* pObj = foo();
func(*pObj); //was that NULL?
--
Mark Ping
em****@soda.CSUA.Berkeley.EDU
Jul 23 '05 #55
Steven T. Hatton wrote:
Larry I Smith wrote:
Steven T. Hatton wrote:
John Carson wrote:

"Steven T. Hatton" <ch********@germania.sup> wrote in message
news:as********************@speakeasy.net
>In your example, you are not trying to pass null, you are trying to
>pass a literal.
He is passing NULL which is the same as 0.
'0', when it appears in your code, is a literal. If the reference were
const, the code /would/ compile.

In C++ NULL is zero (0).


Exactly my point. It is NOT a null pointer, it is a literal.
#include <iostream>
#include <string>

struct Stuff
{
int a;
double b;
};

void func(const Stuff& obj)
{
obj.a = 1;
}

int main()
{
Stuff s;
Stuff *sp = 0;

func(s);
// the next 3 produce comple time errors
func(0);
func(NULL);
func(sp);


The error on the last example is because you are passing a pointer to a non
pointer type, and has nothing to do with the value of the type. In the
pervious examples you are passing an integer literal which is likewise
illegal.


No, it is because the stupid programmer is invoking undefined
behavior by deref'ing a null pointer; it has nothing to do with
func().

// the next one is a stupid programmer error - deref'ing a NULL
// pointer. it crashes before func() is called - a good reason
// to use ref's exclusively rather than pointers.
func(*sp);

return 0;
}
The pros & cons of refs vs pointers could be argued forever.
Advocates of the different approaches will probably never
agree. So let's not beat it to death anymore.

Regards,
Larry

Jul 23 '05 #56
em****@soda.csua.berkeley.edu (E. Mark Ping) wrote in news:daubp5$rst$1
@agate.berkeley.edu:
In article <19*************************@posting.google.com> ,
Mr A <al**************@hotmail.com> wrote:
Any comments on why this could be a bad idea or do you think it's
just a matter of taste?
Just because your signature is func(Object& obj), it won't prevent
others from passing in pointers:


Without them invoking undefined behaviour first, yes it will. Any sane
programmer will check their pointers for validity before attempting to
derference it. (Either explicitly by testing it, or implicitly by the
enforcement of preconditions.).
Object* pObj = foo();
func(*pObj); //was that NULL?


Undefined behaviour. The caller has attempted to dereference NULL. Not
func()'s problem.

Jul 23 '05 #57
Mr A wrote:
I've been thinking about passing parameters
using references instead of pointers
in order to emphasize that the parameter must be an object.

Example:

void func(Objec& object); //object must be an object

instead of

void func(Object* object); //object can be NULL

I belive that this is a good idea
since, in the reference case, it's clear that NULL is not an option.
It's also clear that NULL is an option
when a pointer is expected (stating the obvious :-) ).
The code becomes somewhat more self-documenting.

Any comments on why this could be a bad idea?
Or do you think it's just a matter of taste?


Pass by reference is *always* preferred over passing a pointer.
First, you should pass a *const* reference or pointer:

void func(const Object& object);

or

void func(const Object* object);

unless the object *must* be modified in place.
Second, if your function must modify an object,
you should return a reference or pointer to that object:

Object& func(const Object& object) {
// modify object
return object;
}

or

Object* func(const Object* object) {
// modify *object
return object;
}

instead of void so that you can use the function in an expression.
Finally, whenever possible, you should return by value:

Object func(void) {
Object object;
// modify object
return object;
}
Jul 23 '05 #58
E. Robert Tisdale wrote:
Mr A wrote:
I've been thinking about passing parameters
using references instead of pointers
in order to emphasize that the parameter must be an object.

Example:

void func(Objec& object); //object must be an object

instead of

void func(Object* object); //object can be NULL

I belive that this is a good idea
since, in the reference case, it's clear that NULL is not an option.
It's also clear that NULL is an option
when a pointer is expected (stating the obvious :-) ).
The code becomes somewhat more self-documenting.

Any comments on why this could be a bad idea?
Or do you think it's just a matter of taste?

Pass by reference is *always* preferred over passing a pointer.
First, you should pass a *const* reference or pointer:

void func(const Object& object);

or

void func(const Object* object);

unless the object *must* be modified in place.
Second, if your function must modify an object,
you should return a reference or pointer to that object:

//Object& func(const Object& object) {

Object& func(Object& object) { // modify object
return object;
}

or

//Object* func(const Object* object) { Object* func(Object* object) { // modify *object
return object;
}

instead of void so that you can use the function in an expression.
Finally, whenever possible, you should return by value:

Object func(void) {
Object object;
// modify object
return object;
}

Jul 23 '05 #59
John Carson wrote:
"David White" <no@email.provided> wrote in message
news:KX********************@nasal.pacific.net.au
Try passing a null pointer to ::strlen(). Just
because a pointer is passed doesn't necessarily mean that the
function will permit it to be null.
Really? When I try this, the code compiles and the program crashes
when run.


Precisely. Isn't a crash is good evidence that strlen doesn't permit passing
a null pointer?
Of course, functions can check for null pointers (though
this won't stop compilation) but at least my copy of strlen
apparently doesn't.
Neither does mine. I made sure it crashed before using it as an example.
After all, there's no sensible length it can return for a null pointer.
One thing about the reference case is that you can't tell from the
call whether it is pass by value or pass by reference. In the pointer
case it is at least obvious from the call that an address is being
passed, so you are alerted that the function might change the object.

void fooptr(int * ptr);
void fooptr(const int * ptr);

vs

void fooref(int & ref);
void fooref(const int & ref);

int main()
{
int x;
fooptr(&x);
fooref(x);
}

What do you know from the fooptr(&x) call that you don't know from the
fooref(x) call or vice versa?


Nothing. My point is that passing by value is very common, so the occasional
non-const reference doesn't stand out at all.
The only time you can know something from a function call is if you
*never* use references.
No, if you never use non-const references.
In that case, when you pass by value you know
that the value won't be changed. If you pass by pointer, you still
don't know either way.
That doesn't matter. You know it _might_ be changed.
The situation in which you never use
references is of course when programming in C. I think this
preference for pointers is just a hangover from C.
That's probably partly true, but I don't think it helps to deny the
existence of thousands of programmers who are more familiar with C than C++,
and for whom pass-by-reference might easily be assumed to be pass-by-value.
The real point is surely that when you call a function you are
supposed to know what it does.

You figure out what you want done and
you call a function that is documented to do it. You don't call
functions because the function call "looks" like it will do what you
want.


I might not have called the function. I might be reading someone else's
code.

As it happens, I'm not as opposed to passing by non-const reference as it
might appear. I still think it's probably a good idea to avoid it, but in
practice it's probably rare that a programmer won't already know what a
function does, or won't be able to determine a function's actions from its
name, so it's unlikely to be a significant cause of misunderstanding. I
mentioned it mainly as something to consider.

DW
Jul 23 '05 #60
"David White" <no@email.provided> wrote in message
news:DA********************@nasal.pacific.net.au
John Carson wrote:
The only time you can know something from a function call is if you
*never* use references.


No, if you never use non-const references.


Correct.

--
John Carson
Jul 23 '05 #61
In message <da**********@nntp1.jpl.nasa.gov>, E. Robert Tisdale
<E.**************@jpl.nasa.gov> writes
E. Robert Tisdale wrote:


[...]
Second, if your function must modify an object,
you should return a reference or pointer to that object:
//Object& func(const Object& object) {

Object& func(Object& object) {
// modify object
return object;
}
or
//Object* func(const Object* object) {

Object* func(Object* object) {
// modify *object
return object;
}
instead of void
Ugh. I'd be more inclined to say "if your function modifies an object,
it MUST NOT return a reference to that object." It just invites the
reader to misinterpret what's going on. If you write

f(a);
g(a);

it's obvious that the functions are not being called for their return
values, and therefore some side effect is intended.

If you write

g(f(a));

or even

x = f(a);

it's not obvious to the reader that "a" is in effect used *twice*, even
though it only appears once.

A function which does a single thing cleanly is usually preferable to
one which does two things, or which does the single thing obscurely.
so that you can use the function in an expression.


Which is only a benefit to authors of obfuscated code.

--
Richard Herring
Jul 23 '05 #62
Larry I Smith wrote:
Steven T. Hatton wrote:
Larry I Smith wrote:
int main()
{
Stuff s;
Stuff *sp = 0;

func(s);
// the next 3 produce comple time errors
func(0);
func(NULL);
func(sp);


The error on the last example is because you are passing a pointer to a
non
pointer type, and has nothing to do with the value of the type. In the
pervious examples you are passing an integer literal which is likewise
illegal.


No, it is because the stupid programmer is invoking undefined
behavior by deref'ing a null pointer; it has nothing to do with
func().


We are talking about compile time errors, not runtime. The examples are all
detectable violations of the language rules. In the first two cases you
are attempting to initialize a non-const references with a temporary, and
in the third case you are trying to initialize a reference to a type with a
pointer to the type. That's a type missmatch. None of these has anything
to do with the value of the argument passed.

--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #63
ni*****@microsoft.com wrote:
Steven T. Hatton wrote:
ni*****@microsoft.com wrote:
> Steven T. Hatton wrote: Actually it is an integer literal which when assigned to a pointer to
type T
is converted to a null pointer constant to T. The distinction may seem
trivial, but the error is not due to the fact that 0 is being used. It
is due to the fact that a literal is being used to initialize a temporary
of type int.


True, but that does not contradict what I said.

§4.10
"A null pointer constant is an integral constant expression (5.19)
rvalue of integer type that evaluates to zero. A null pointer constant
can be converted to a pointer type; the result is the null pointer
value of that type..."

As I pointed out, the null pointer constant is not the same thing as a
null pointer so I was agreeing with you.


This is, perhaps, pedantic, but 0 and NULL are integer literals. They are
replaced by the compiler with (instructions to generate) temporary integer
values which are used to initialize the lvalues to which they are assigned.
A null pointer constant would be something like `const int null_ptr = 0'.
In that case null_ptr would live throughout the life of the scope in which
it is defined. And that probably means global in this case.

Using null_ptr instead of NULL is also an error, but it is a different kind
of error. In the case of NULL, the error is attempting to initialize a
non-const reference with a temporary. In the case of null_ptr the error is
attempting to initialize a non-const reference with a const object. In the
former, you are trying to establish a persistent means of accessing
something which is transient. In the latter, you are trying to establish a
means of accessing and modifying something that is constant.
Undefined simply means you've left the world of standard C++ and
your program could do anything. As some on Usenet are fond of saying,
blue demons could fly out of your nose.

You enter the land of undefined behavior as soon as you dereference
a null pointer. How and when that manifests in some particular way
in a particular case is... well... undefined.
Exactly. It's the C++ analog to proving 1 = 0 in mathematics, or true =
false formal logic.
The segfault *is* the undefined behavior that results from the attempt to
dereference a null pointer.


A segfault is one possible consequence of doing something that causes
undefined behavior.


I am aware that the Standard does not dictate that a segfault will happen.
There are times when undefined behavior is identical to what would happen
if the statement resulting in undefined behavior did not appear in the
program. A crash is actually more desirable than the alternative of having
the program continue to run with some subtle undefined behavior lurking in
it. For example, the program may run perfectly for almost all input, but
when it encounters a field beyond a certain length, it may truncate, or
overwrite the end of the field with garbage.
§5.3.1/1
"The unary * operator performs /indirection/: the expression to which it
is applied shall be a pointer to an object type, or a pointer to a
function type and the result is an lvalue referring to the object or
function to which the expression points. If the type of the expression is
?pointer to T,? the type of the result is ?T.?"

An lvalue is said to refer to specific storage, so I would say that
pretty much means returning an address.


An lvalue is just an expression that refers to an object or function
(§3.10) and an object occupies storage. A local variable of type int
is an lvalue, for example. This says nothing about how a C++
implementation might choose to represent pointers and references
under the hood.


But to say that something occupies storage basically means it has an address
of some kind. I don't care if you want to say an lvalue is a box in a
warehouse. There will still be some way of referring to it by means of
coordinates.

No, applying the indirection operator to a variable of type pointer to
type
T is the definition of a behavior. The _result_ is undefined.


Very well, the result of dereferencing a null pointer is undefined.


This is probably a more important distinction than it may seem. Undefined
behavior may appear anywhere, and at any time in the execution of the
program after the statement producing it has been encountered.
For the record, I don't believe I actually said the result was a null
reference.


You said "AFAIK, you *can* pass a null to func() in your example",
and the example in question declared func as taking a parameter of
reference type.


I believe that was in response to the example using the integer literal 0 as
the argument to a function taking a non-const reference as a parameter. My
point was that you /can/ dereference a pointer and use it as an argument in
that situation. That code will compile, and the pointer being dereferenced
may be null when the program is executed. I had left it as implied that
this is probably not what the programmer would want.

Technically, the null pointer is passed to the indirection expression
appearing in the argument list, and the (result of evaluating the)
indirection expression is passed to func(). So what I really meant by
'passing a null' is that a null pointer can appear in the indirection
expression passed as an argument to func() without a compiler error being
produced.
At a practical level, I think I understand your general point that
using references instead of pointers does not really protect you
against undefined behavior. Undefined behavior could still occur
if you form a reference by dereferencing a null pointer, return
a reference to a local object, etc.
My point in the particular instance was that the examples presented by the
OP were not addressing the issues they were intended to address.
However, my response would be that it's the responsibility of
the code that initializes the reference (e.g., by dereferencing
a pointer in your example) to make sure the object actually exists.
As a general rule, I don't believe that's possible. Firstly, you don't want
to dereference a null pointer, you want to compare it to 0, or compare the
result of a dynamic_cast on it to 0. That protects against dereferencing a
null pointer. Unfortunately, you cannot depend on the result of a
dynamic_cast to determine that an object is valid. A dynamic_cast will
only tell you if the operand "claims to be" valid. For example, after
calling delete on an object of type Foo, the memory holding Foo may
(probably will) still hold exactly what it held before the delete.
dynamic_casting a pointer to that memory location will result in returning
a pointer to type Foo with the address of the deleted object. The object
is, by definition, invalid but may well behave as if it were valid.
That's the code that needs to be scrutinized for possible undefined
behavior. A function that takes a reference parameter should be
able to assume that the reference is actually bound to an object;
if it is not then the program is already undefined and the fault
lies elsewhere.


Yes, and I believe part of the OP's argument for using references over
pointers was that it reduces the need for detecting null pointers, and thus
results in more efficient code. I don't believe that reasoning is viable.
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #64
Steven T. Hatton wrote:
[snip]

Yes, and I believe part of the OP's argument for using references over
pointers was that it reduces the need for detecting null pointers, and thus
results in more efficient code. I don't believe that reasoning is viable.


Well, many folks believe that it is viable.

If references are evil and one should only use pointers (as you
have repeated over and over and over in this thread), then we might
as well have stayed with C.

This is like a religious discussion - neither point of
view will convince the other.

We'll keep using references, but to each his own...

Regards,
Larry
Jul 23 '05 #65
Larry I Smith wrote:
Steven T. Hatton wrote:
[snip]

Yes, and I believe part of the OP's argument for using references over
pointers was that it reduces the need for detecting null pointers, and
thus
results in more efficient code. I don't believe that reasoning is
viable.
Well, many folks believe that it is viable.


The truth of an assertion is not determined by the number of people who
ascribe to the belief that it is true.
If references are evil and one should only use pointers (as you
have repeated over and over and over in this thread),
I have never said references are evil, and I have never said we should only
use pointers. AAMOF, I have rather clearly stated that there /are/
reasonable places where using references as function parameters makes
sense.
then we might as well have stayed with C.
References are only one of many C++ features which are not present in C.
Why would I not want the other features even if references were excluded
from C++?
This is like a religious discussion - neither point of view will convince
the other.


Perhaps, but presenting specious arguments to support your position is
potentially harmful to people who accept them uncritically.

--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #66
Richard Herring wrote:
E. Robert Tisdale writes
Second, if your function must modify an object,
you should return a reference or pointer to that object:
//Object& func(const Object& object) {
Object& func(Object& object) {
// modify object
return object;
}
or
//Object* func(const Object* object) {


Object* func(Object* object) {
// modify *object
return object;
}
instead of void
Ugh. I'd be more inclined to say,
"If your function modifies an object,
it MUST NOT return a reference to that object."
It just invites the reader to misinterpret what's going on.
If you write

f(a);
g(a);

it's obvious that the functions are not being called for their return
values, and therefore some side effect is intended.


But the same is true if you invoke

func(a);

You don't *need* to use the returned reference (pointer).
If you write

g(f(a));

or even

x = f(a);

it's not obvious to the reader that "a" is in effect used *twice*,
even though it only appears once.
Isn't it "obvious" that, in

std::cout << "i = " << 42 << std::endl;

ostream std::cout is used *thrice*?
A function which does a single thing cleanly is usually preferable to
one which does two things, or which does the single thing obscurely.


Would you then agree that
a function should *not* modify two or more arguments?
so that you can use the function in an expression.


Which is only a benefit to authors of obfuscated code.


What's wrong with using functions in expressions?
If you are going to call one void function after another,
you might as well write your program in assembler.
Jul 23 '05 #67
Steven T. Hatton wrote:
I know of two companies who have concluded that passing by reference is, in
general, a bad choice. Trolltech, and SuSE.


I don't know about SuSE, but I wouldn't take Trolltech too seriously
when it comes to API design.

Bob

Jul 23 '05 #68
be****@pacbell.net wrote:
Steven T. Hatton wrote:
I know of two companies who have concluded that passing by reference is,
in
general, a bad choice. Trolltech, and SuSE.


I don't know about SuSE, but I wouldn't take Trolltech too seriously
when it comes to API design.

Bob


They do a few things I don't care for and there are some features I wish Qt
provided. But the success of the KDE speaks for itself. They are certainly
one of the leaders in C++ GUI toolkit development.

I remember what the Unix desktop looked like in 1997.
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #69
Steven T. Hatton wrote:
be****@pacbell.net wrote:
Steven T. Hatton wrote:
I know of two companies who have concluded that passing by reference is,
in
general, a bad choice. Trolltech, and SuSE.
I don't know about SuSE, but I wouldn't take Trolltech too seriously
when it comes to API design.

Bob


They do a few things I don't care for and there are some features I wish Qt
provided. But the success of the KDE speaks for itself. They are certainly
one of the leaders in C++ GUI toolkit development.


Yes, the success of KDE speaks for itself. It does not, however, speak
for the quality of APIs developed at Trolltech or the recommendations
they make. Success in the market usually doesn't mean anything more
than success in the market.
I remember what the Unix desktop looked like in 1997.


So do I. <shudder>

Bob

Jul 23 '05 #70
Steven T. Hatton wrote:
ni*****@microsoft.com wrote:
Steven T. Hatton wrote:
ni*****@microsoft.com wrote:

> Steven T. Hatton wrote:
Actually it is an integer literal which when assigned to a pointer to
type T
is converted to a null pointer constant to T. The distinction may seem
trivial, but the error is not due to the fact that 0 is being used. It
is due to the fact that a literal is being used to initialize a temporary
of type int.
True, but that does not contradict what I said.

§4.10
"A null pointer constant is an integral constant expression (5.19)
rvalue of integer type that evaluates to zero. A null pointer constant
can be converted to a pointer type; the result is the null pointer
value of that type..."

As I pointed out, the null pointer constant is not the same thing as a
null pointer so I was agreeing with you.


This is, perhaps, pedantic, but 0 and NULL are integer literals.

[snip]

Read the quote from the standard above. I know what an integer
literal is. It just happens that the standard defines the term
"null pointer constant" to mean any "integral constant expression
.... that evaluates to zero." The integer literal 0 is one example
of a null pointer constant. Here's another example:

void* p = 2 - 2;

The integral constant expression 2 - 2 is a null pointer constant
by the above definition. Therefore p is initialized to the null
pointer value.

Incidentally, this implicit conversion can be useful for
compile-time asserts, e.g.,

// CompileTimeAssertPow2
// value field is 1 if N is a power of two; otherwise,
// instantiating value yields a compile-time error.
template<int N>
struct CompileTimeAssertPow2
{
static const int value =
static_cast<void*>(0) == (N & (N-1));
}

[snip]
§5.3.1/1
"The unary * operator performs /indirection/: the expression to which it
is applied shall be a pointer to an object type, or a pointer to a
function type and the result is an lvalue referring to the object or
function to which the expression points. If the type of the expressionis
?pointer to T,? the type of the result is ?T.?"

An lvalue is said to refer to specific storage, so I would say that
pretty much means returning an address.


An lvalue is just an expression that refers to an object or function
(§3.10) and an object occupies storage. A local variable of type int
is an lvalue, for example. This says nothing about how a C++
implementation might choose to represent pointers and references
under the hood.


But to say that something occupies storage basically means it has an address
of some kind. I don't care if you want to say an lvalue is a box in a
warehouse. There will still be some way of referring to it by means of
coordinates.


Sure, every object has to have an address. However, it doesn't
follow that the internal representation of a pointer or reference
is the address of the pointee. It could be something else -- like
an index into an array of object descriptors maintained by the
run-time system, or an address plus some other bits that encode
type information, etc.
No, applying the indirection operator to a variable of type pointer to
type
T is the definition of a behavior. The _result_ is undefined.


Very well, the result of dereferencing a null pointer is undefined.


This is probably a more important distinction than it may seem. Undefined
behavior may appear anywhere, and at any time in the execution of the
program after the statement producing it has been encountered.


For convenience, let's use the term 'cause' to denote the
statement or expression that results in undefined behavior
'effect' to denote the undefined behavior itself.

So let's consider an example involving references:

int func(int& r)
{
return r;
}
int main()
{
int* p = 0;
return func(*p);
}

Now we both agree that the 'cause' of the undefined behavior
is the expression *p in main. The 'effect' could be anything
at any time, but let's suppose that in this case, it is a
"seg fault" during the execution of func.

You seem to think that the fact that the effect occurred in
func is somehow an indictment of func -- specifically of the
fact that it takes a reference parameter.

However, I would argue that where the effect occurred is
irrelevant, except for debugging purposes. The proper focus
of our attention is the cause of the undefined behavior.
Clearly, main is at fault here. Any code that dereferences
a pointer should "know" that the pointer is valid and not
null.
For the record, I don't believe I actually said the result was a null
reference.


You said "AFAIK, you *can* pass a null to func() in your example",
and the example in question declared func as taking a parameter of
reference type.


I believe that was in response to the example using the integer literal 0as
the argument to a function taking a non-const reference as a parameter. My
point was that you /can/ dereference a pointer and use it as an argument in
that situation. That code will compile, and the pointer being dereferenced
may be null when the program is executed. I had left it as implied that
this is probably not what the programmer would want.


You were responding to the OP statement that using references makes the
code safer and more self-documenting because a reference cannot be
null.
Technically, the null pointer is passed to the indirection expression
appearing in the argument list, and the (result of evaluating the)
indirection expression is passed to func(). So what I really meant by
'passing a null' is that a null pointer can appear in the indirection
expression passed as an argument to func() without a compiler error being
produced.


True, but that doesn't mean a null refrence has been passed to func().
It means the caller has caused undefined behavior. The distinction is
significant because it suggests where the fix needs to be made: not in
func itself but in the calling statement that dereferences the pointer.
At a practical level, I think I understand your general point that
using references instead of pointers does not really protect you
against undefined behavior. Undefined behavior could still occur
if you form a reference by dereferencing a null pointer, return
a reference to a local object, etc.


My point in the particular instance was that the examples presented by the
OP were not addressing the issues they were intended to address.
However, my response would be that it's the responsibility of
the code that initializes the reference (e.g., by dereferencing
a pointer in your example) to make sure the object actually exists.


As a general rule, I don't believe that's possible.

[snip]

True, there is no run-time test that can reliably determine whether
a pointer is valid. By "make sure" I just meant the programmer needs
to be sure -- by clearly specifying the function's contract, enforcing
invariants, etc. Thus if the caller if func() initializes a reference
by deferencing a pointer, which turns out to be null, the fault lies
not with func() but with the caller -- or perhaps with some function
farther up the stack for passing invalid arguments to the caller.
That's the code that needs to be scrutinized for possible undefined
behavior. A function that takes a reference parameter should be
able to assume that the reference is actually bound to an object;
if it is not then the program is already undefined and the fault
lies elsewhere.


Yes, and I believe part of the OP's argument for using references over
pointers was that it reduces the need for detecting null pointers, and thus
results in more efficient code. I don't believe that reasoning is viable.


If func takes a reference and the caller has a pointer, then the caller
has to deference the pointer. So in this case we've just moved the
pointer derefence, not eliminated it.

However, perhaps the caller already has something other than a pointer,
e.g., a local variable. By making func take a reference, we eliminate
the need for a pointer entirely. In this way, using reference
parameters
instead of pointers can give a net reduction in the total number of
pointers.

If one adopts a programming style which results in pointers being
relatively rare, it becomes feasable to scrutinize the remaining
pointers
even more closely for possible undefined behavior.

Jul 23 '05 #71
Of course that's not a problem with the definition of dynamic_cast.
Except that I don't really have any control over how it's implemented.
So if on one of my primary platforms (Windows) it's always a
performance bottleneck, that means I have to avoid it except where
performance is not an issue.

Stuart

Jul 23 '05 #72
In article <Xn*******************************@207.35.177.135> ,
Andre Kostur <nn******@kostur.net> wrote:
Mark Ping) wrote:
Just because your signature is func(Object& obj), it won't prevent
others from passing in pointers:


Without them invoking undefined behaviour first, yes it will. Any sane
programmer will check their pointers for validity before attempting to
derference it. (Either explicitly by testing it, or implicitly by the
enforcement of preconditions.).
Object* pObj = foo();
func(*pObj); //was that NULL?


Undefined behaviour. The caller has attempted to dereference NULL. Not
func()'s problem.


This has all the benefit of "neener neener neener, it's your fault".
No compilers I know of track pointers and terminate as soon as a null
pointer is derefereneced. So while this is true formally, it's of no
real use practically.

At any rate it's an academic distinction anyway. I said I prefer to
use ref arguments unless a null pointer is a valid argument (in which
case you have to use pointers).
--
Mark Ping
em****@soda.CSUA.Berkeley.EDU
Jul 23 '05 #73
ni*****@microsoft.com wrote:
Steven T. Hatton wrote:
ni*****@microsoft.com wrote:
> Steven T. Hatton wrote: This is, perhaps, pedantic, but 0 and NULL are integer literals.

[snip]

Read the quote from the standard above. I know what an integer
literal is. It just happens that the standard defines the term
"null pointer constant" to mean any "integral constant expression
... that evaluates to zero." The integer literal 0 is one example
of a null pointer constant. Here's another example:


Yes, I looked it up, and indeed an integer literal is an integral constant
expression.
void* p = 2 - 2;

The integral constant expression 2 - 2 is a null pointer constant
by the above definition. Therefore p is initialized to the null
pointer value.

Incidentally, this implicit conversion can be useful for
compile-time asserts, e.g.,

// CompileTimeAssertPow2
// value field is 1 if N is a power of two; otherwise,
// instantiating value yields a compile-time error.
template<int N>
struct CompileTimeAssertPow2
{
static const int value =
static_cast<void*>(0) == (N & (N-1));
}
I'll have to take your word that this is useful.
For convenience, let's use the term 'cause' to denote the
statement or expression that results in undefined behavior
'effect' to denote the undefined behavior itself.

So let's consider an example involving references:

int func(int& r)
{
return r;
}
int main()
{
int* p = 0;
return func(*p);
}

Now we both agree that the 'cause' of the undefined behavior
is the expression *p in main. The 'effect' could be anything
at any time, but let's suppose that in this case, it is a
"seg fault" during the execution of func.

You seem to think that the fact that the effect occurred in
func is somehow an indictment of func -- specifically of the
fact that it takes a reference parameter.
No. It is just a counterexample presented to demonstrate that the compiler
will not prevent you from attempting to pass a dereferenced null pointer to
func().
You were responding to the OP statement that using references makes the
code safer and more self-documenting because a reference cannot be
null.
Actually what the Standard says is that a reference connot be null in a well
defined program. I am beginning to understand what the comment about
self-documentation was intending. I was looking at it from the other point
of view. For what I've been doing, it makes no sense to work with
references. Shared data is part of the conceptual design, and using
pointers is therefore necessary. In order to pass a reference, I would
have to dereference a pointer. It would be a deviation from the pattern to
create a function that took a reference rather than a pointer.

I guess if I were working with data forms, or something like that, it might
make more sense to pass references.
Technically, the null pointer is passed to the indirection expression
appearing in the argument list, and the (result of evaluating the)
indirection expression is passed to func(). So what I really meant by
'passing a null' is that a null pointer can appear in the indirection
expression passed as an argument to func() without a compiler error being
produced.


True, but that doesn't mean a null refrence has been passed to func().


It doesn't mean it hasn't been either.
It means the caller has caused undefined behavior. The distinction is
significant because it suggests where the fix needs to be made: not in
func itself but in the calling statement that dereferences the pointer.


Agreed. I can see how one might argue that there is an advantage to that if
there is no need for polymorphic behavior, using reference may well be
preferable. OTOH, the fact remains that information is not available at
the point where the function is called which might be communicated by
passing a pointer.
> At a practical level, I think I understand your general point that
> using references instead of pointers does not really protect you
> against undefined behavior. Undefined behavior could still occur
> if you form a reference by dereferencing a null pointer, return
> a reference to a local object, etc.


My point in the particular instance was that the examples presented by
the OP were not addressing the issues they were intended to address.
> However, my response would be that it's the responsibility of
> the code that initializes the reference (e.g., by dereferencing
> a pointer in your example) to make sure the object actually exists.


As a general rule, I don't believe that's possible.

[snip]

True, there is no run-time test that can reliably determine whether
a pointer is valid. By "make sure" I just meant the programmer needs
to be sure -- by clearly specifying the function's contract, enforcing
invariants, etc. Thus if the caller if func() initializes a reference
by deferencing a pointer, which turns out to be null, the fault lies
not with func() but with the caller -- or perhaps with some function
farther up the stack for passing invalid arguments to the caller.


Yes. And if you can constrain the parameters to the point where you are not
using polymorphism, or if you are willing to either take the address of the
reference, or program by exception, then it may make some sense to pass by
reference. I've just not been in a situation where that is applicable.
> That's the code that needs to be scrutinized for possible undefined
> behavior. A function that takes a reference parameter should be
> able to assume that the reference is actually bound to an object;
> if it is not then the program is already undefined and the fault
> lies elsewhere.


Yes, and I believe part of the OP's argument for using references over
pointers was that it reduces the need for detecting null pointers, and
thus
results in more efficient code. I don't believe that reasoning is
viable.


If func takes a reference and the caller has a pointer, then the caller
has to deference the pointer. So in this case we've just moved the
pointer derefence, not eliminated it.

However, perhaps the caller already has something other than a pointer,
e.g., a local variable. By making func take a reference, we eliminate
the need for a pointer entirely. In this way, using reference
parameters
instead of pointers can give a net reduction in the total number of
pointers.

If one adopts a programming style which results in pointers being
relatively rare, it becomes feasable to scrutinize the remaining
pointers
even more closely for possible undefined behavior.


It also has to do with the design domain. I'm also wondering how this
impacts such notions as abstract interfaces.

--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #74
Steven T. Hatton wrote:
Larry I Smith wrote:
Steven T. Hatton wrote:
[snip]
Yes, and I believe part of the OP's argument for using references over
pointers was that it reduces the need for detecting null pointers, and
thus
results in more efficient code. I don't believe that reasoning is
viable.

Well, many folks believe that it is viable.


The truth of an assertion is not determined by the number of people who
ascribe to the belief that it is true.
If references are evil and one should only use pointers (as you
have repeated over and over and over in this thread),


I have never said references are evil, and I have never said we should only
use pointers. AAMOF, I have rather clearly stated that there /are/
reasonable places where using references as function parameters makes
sense.
then we might as well have stayed with C.


References are only one of many C++ features which are not present in C.
Why would I not want the other features even if references were excluded
from C++?
This is like a religious discussion - neither point of view will convince
the other.


Perhaps, but presenting specious arguments to support your position is
potentially harmful to people who accept them uncritically.


Sigh....

Your dozens of posts also seem specious - streams of words asserting
that only pointers should be used in a well designed program; that
references are used only by the unwashed and uneducated, and that
your mission is to convince us of the error of our ways (at least
that's the way your posts read).

References are quite useful to many (most?) of us.

I counted the number of pointers and references used in a WEB
Services app just completed by one of our development teams:
37 pointers, 1983 references (in 300K+ lines of code).
This statistic means nothing in particular; I include it
merely to show that many apps work quite well with designs
that use references.

Regards,
Larry
Jul 23 '05 #75
Steven T. Hatton wrote:
ni*****@microsoft.com wrote: [snip]

For convenience, let's use the term 'cause' to denote the
statement or expression that results in undefined behavior
'effect' to denote the undefined behavior itself.

So let's consider an example involving references:

int func(int& r)
{
return r;
}
int main()
{
int* p = 0;
return func(*p);
}

Now we both agree that the 'cause' of the undefined behavior
is the expression *p in main. The 'effect' could be anything
at any time, but let's suppose that in this case, it is a
"seg fault" during the execution of func.

You seem to think that the fact that the effect occurred in
func is somehow an indictment of func -- specifically of the
fact that it takes a reference parameter.


No. It is just a counterexample presented to demonstrate that the compiler
will not prevent you from attempting to pass a dereferenced null pointer to
func().


Sure, a compiler will not usually prevent you from causing undefined
behavior. However, the use references did not cause or contribute to
the undefined behavior.

If your point is that reference parameters are not a silver bullet
that make undefined behavior a thing of the past, then I agree.
They can help to some degree insofar as they help one reduce the
use of pointers generally.
You were responding to the OP statement that using references makes the
code safer and more self-documenting because a reference cannot be
null.


Actually what the Standard says is that a reference connot be null in a well
defined program.


The purpose of the standard is to specify what a "well-defined program"
is so this isn't much of a caveat. Once you start invoking undefined
behavior your program is no longer a C++ program as defined by the
standard.
I am beginning to understand what the comment about
self-documentation was intending. I was looking at it from the other point
of view. For what I've been doing, it makes no sense to work with
references. Shared data is part of the conceptual design, and using
pointers is therefore necessary. In order to pass a reference, I would
have to dereference a pointer. It would be a deviation from the pattern to
create a function that took a reference rather than a pointer.

I guess if I were working with data forms, or something like that, it might
make more sense to pass references.
I don't deny there are many cases where pointers are the best choice.
However, it's hard to imagine a program that doesn't (also) have, say,
local variables.
Technically, the null pointer is passed to the indirection expression
appearing in the argument list, and the (result of evaluating the)
indirection expression is passed to func(). So what I really meant by
'passing a null' is that a null pointer can appear in the indirection
expression passed as an argument to func() without a compiler error being
produced.


True, but that doesn't mean a null refrence has been passed to func().


It doesn't mean it hasn't been either.


If you want to talk about what happens *after* you invoke undefined
behavior then we're no longer talking about C++. In C++ there is no
such thing as a null reference.
It means the caller has caused undefined behavior. The distinction is
significant because it suggests where the fix needs to be made: not in
func itself but in the calling statement that dereferences the pointer.


Agreed. I can see how one might argue that there is an advantage to that if
there is no need for polymorphic behavior, using reference may well be
preferable.


References don't preclude polymorphism.
OTOH, the fact remains that information is not available at
the point where the function is called which might be communicated by
passing a pointer.


This is a separate objection from the one about undefined behavior.
I think it is a legitimate disadvantage of using references for out
parameters, but I personally still tend to prefer references and
compensate by naming.

[snip]
True, there is no run-time test that can reliably determine whether
a pointer is valid. By "make sure" I just meant the programmer needs
to be sure -- by clearly specifying the function's contract, enforcing
invariants, etc. Thus if the caller if func() initializes a reference
by deferencing a pointer, which turns out to be null, the fault lies
not with func() but with the caller -- or perhaps with some function
farther up the stack for passing invalid arguments to the caller.


Yes. And if you can constrain the parameters to the point where you are not
using polymorphism, or if you are willing to either take the address of the
reference, or program by exception, then it may make some sense to pass by
reference. I've just not been in a situation where that is applicable.


Refererences don't preclude polymorphism.

Also, who said anything about "programming by exception"? If there
is a pointer to be dereferenced, then whoever does the dereferencing
is responsible for "knowing" that the pointer is not null -- either
by a runtime check or by understanding the invariants at that point.
The same thing applies whether the pointer is dereferenced in the
called function (i.e., the function takes a pointer) or at the call
site (i.e., the function takes a reference).

I don't see how either is inherently safer, except in cases where
use of a reference parameter elimaintes the pointer entirely (i.e.,
the caller didn't have a pointer to begin with). Also, a reference
parameter eliminates any possible ambiguity about whether a function
accepts NULL as a valid argument.

[snip]
If one adopts a programming style which results in pointers being
relatively rare, it becomes feasable to scrutinize the remaining
pointers
even more closely for possible undefined behavior.


It also has to do with the design domain. I'm also wondering how this
impacts such notions as abstract interfaces.


Again, references don't preclude polymorphism. I'll accept that the
design domain is a factor in how many pointers one uses.

Jul 23 '05 #76
John Carson wrote:
"Steven T. Hatton" <ch********@germania.sup> wrote in message
news:yI********************@speakeasy.net
It is actually a prohibitive cost, because it means you can't
use libraries that use non-const references.


No. It only means that you don't do it in *your* libraries. It's
just silly to say you would never use other people's libraries
because they don't conform you your coding conventions.
Unfortunately established practices in C++ are very heterogeneous,
and excluding libraries on the basis of failing to follow some
established convention would probably exclude 90% of all C++ code
_regardless_ of the convention used as a filter.


It is not silly at all. The point is that you want a cheap indicator of what
a function does. Just look at the function call and you know. Well, if that
is the sort of cursory study that is involved, how do you know if the
function is one of "yours" or one from some other library? Plainly you can't
know, so your cheap indicator is as likely to mislead as inform. Sensible
programmers will ignore it.


void Foo(int*);
void Foo(int&);

void A()
{
int x(0);
int& xx(x);

Foo(xx);
}

void B()
{
int y(0);
int* yy(&y);

Foo(yy);
}

Looking at these two functions, I don't see how it's any easier to see
that the call to Foo() in B() is likely to change y than it is to see
that the call to Foo() in A() will change x.

It's been my experience with large bodies of code that try to use
pointer arguments to signal "may change the argument" (e.g., Qt) is
that it simply doesn't work very well. The theory is that seeing the
"&" at the call site tells you it's a pointer, so you should be aware
that the pointee might change. My contrived example above that the call
site can be easily missing the "&", in which case you're no better off
than you would have been with a reference -- you have to read the
documentation.

A more realistic example of losing the "&" is when a function passes on
a pointer argument to another function:

void F(int* p)
{
...

G(p);

...
}

Bob

Jul 23 '05 #77
Mr A wrote:
I've been thinking about passing parameteras using references instead
of pointers in order to emphasize that the parameter must be an
object.
Always use the weakest language construction with the fewest features. This
implies you should always use references unless you need a pointer's extra
features.

Use a pointer when you need the handle to be a value. The referent - the
invisible thing inside a reference that may secretly be implemented as a
pointer - is not itself a value. You cannot compare it to NULL or re-seat
it. You should not index it, but that's a different concern. (You can index
the address of the referend.)
Exemple:
void func(Objec& object); //object must be an object
The language already enforces object must be related to Objec.

If func() won't change object, prefer this:

void func(Objec const & object);

The const is after the Objec because that's where it _should_ be. The
notation 'const Objec &' is syntactic sugar with no other meaning than
'Objec const &'. Type declarations should put the most important part first.

Finally, folks might tell you to pass by address if you intend to change the
object. This is a "compilable comment", and the best compilable comments
don't change structure. Use an active verb in the function name to indicate
it will change the object:

void updateMembers(Object const & object);
Any comments on why this could be a bad idea or do you think it's just
a matter of taste?


Lot's of stuff is a matter of taste, but not dangerous things like pointers
and references...

--
Phlip
http://www.c2.com/cgi/wiki?ZeekLand
Jul 23 '05 #78
Phlip wrote:
Mr A wrote:
I've been thinking about passing parameteras using references instead
of pointers in order to emphasize that the parameter must be an
object.


Always use the weakest language construction with the fewest features.
This implies you should always use references unless you need a pointer's
extra features.


And hope you never will need them.
Exemple:
void func(Objec& object); //object must be an object


The language already enforces object must be related to Objec.

If func() won't change object, prefer this:

void func(Objec const & object);

The const is after the Objec because that's where it _should_ be. The
notation 'const Objec &' is syntactic sugar with no other meaning than
'Objec const &'. Type declarations should put the most important part
first.


http://www.research.att.com/~bs/bs_f...constplacement
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #79
ni*****@microsoft.com wrote:
Steven T. Hatton wrote:
ni*****@microsoft.com wrote: [snip]
>
> For convenience, let's use the term 'cause' to denote the
> statement or expression that results in undefined behavior
> 'effect' to denote the undefined behavior itself.
>
> So let's consider an example involving references:
>
> int func(int& r)
> {
> return r;
> }
> int main()
> {
> int* p = 0;
> return func(*p);
> }
>
> Now we both agree that the 'cause' of the undefined behavior
> is the expression *p in main. The 'effect' could be anything
> at any time, but let's suppose that in this case, it is a
> "seg fault" during the execution of func.
>
> You seem to think that the fact that the effect occurred in
> func is somehow an indictment of func -- specifically of the
> fact that it takes a reference parameter.


No. It is just a counterexample presented to demonstrate that the
compiler will not prevent you from attempting to pass a dereferenced null
pointer to func().


Sure, a compiler will not usually prevent you from causing undefined
behavior. However, the use references did not cause or contribute to
the undefined behavior.


Had that occurred in a program that otherwise used pointers, one might argue
that the anomalous use of a reference /did/ constribute to the problem.
If your point is that reference parameters are not a silver bullet
that make undefined behavior a thing of the past, then I agree.
They can help to some degree insofar as they help one reduce the
use of pointers generally.
I guess if there is a situation inwhich references are useful as parameters,
then perhaps they should be used. I haven't encountered a lot of
situations like that. Usually my function calls change the state of the
object of which the function is a member. If there are parameters, they
are typically pretty lightweight and usually not modified by the call.
Actually what the Standard says is that a reference connot be null in a
well defined program.


The purpose of the standard is to specify what a "well-defined program"
is so this isn't much of a caveat. Once you start invoking undefined
behavior your program is no longer a C++ program as defined by the
standard.


There is a significant difference between what is forbidden and what is left
undefined. As I understand things, code that results in undefined behavior
is not an error, and the compiler is not obligated to warn you about it,
and should probably not produce an error when it encounters such code.
IOW, you're on your own.
I guess if I were working with data forms, or something like that, it
might make more sense to pass references.


I don't deny there are many cases where pointers are the best choice.
However, it's hard to imagine a program that doesn't (also) have, say,
local variables.


Most of the data is stored in containers which are typically operated on by
member functions of the class that owns the container.
> True, but that doesn't mean a null refrence has been passed to func().


It doesn't mean it hasn't been either.


If you want to talk about what happens *after* you invoke undefined
behavior then we're no longer talking about C++. In C++ there is no
such thing as a null reference.


My guess is, the reality of what happens is that the result of dereferencing
a null pointer /is/ used to initialize the parameter, and that's where the
segfault comes from. The Standard does not stipulate that this is an
error.
> It means the caller has caused undefined behavior. The distinction is
> significant because it suggests where the fix needs to be made: not in
> func itself but in the calling statement that dereferences the pointer.


Agreed. I can see how one might argue that there is an advantage to that
if there is no need for polymorphic behavior, using reference may well be
preferable.


References don't preclude polymorphism.


That is correct. I was thinking too narrowly.
Yes. And if you can constrain the parameters to the point where you are
not using polymorphism, or if you are willing to either take the address
of the reference, or program by exception, then it may make some sense to
pass by
reference. I've just not been in a situation where that is applicable.


Refererences don't preclude polymorphism.


What I should have said is that you are not using polymorphism the way it is
used in a scenegraph. Which is really more RTTI than polymorphism.
Also, who said anything about "programming by exception"? If there
is a pointer to be dereferenced, then whoever does the dereferencing
is responsible for "knowing" that the pointer is not null -- either
by a runtime check or by understanding the invariants at that point.


I was thinking in terms of the flow control in a scene graph where it is
quite common to use a dynamic_cast in an if() condition.
It also has to do with the design domain. I'm also wondering how this
impacts such notions as abstract interfaces.


Again, references don't preclude polymorphism. I'll accept that the
design domain is a factor in how many pointers one uses.


The comment about abstract interfaces was regarding the use of indirection
to hide the implementation. I believe that's called a pimpl or something
like that. I was also thinking about Apache's C++ DOM binding
recommendation:

http://xml.apache.org/xerces-c/Apach...BindingL3.html

Ironically Qt uses references in most places where Apache uses pointers.

http://doc.trolltech.com/4.0/xml-tools.html

I went from using Xerces-J to Xerces-C++ to QtXml. That was the first time
I had encountered references and was quite confused.
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #80
Steven T. Hatton wrote:
Phlip wrote:
void func(Objec const & object);

The const is after the Objec because that's where it _should_ be. The
notation 'const Objec &' is syntactic sugar with no other meaning
than 'Objec const &'. Type declarations should put the most
important part first.


http://www.research.att.com/~bs/bs_f...constplacement


Well, that's one opinion. I write the 'const' first as well, but only
because that's what almost everyone does, so I did too and now I'm used to
it. However, the form "int const" is more appealing because 'const' is just
a modifier and there can be many modifiers in a single declaration but only
one type. I like the consistency of the type always being first. I think
that putting 'const' in front of it is a bit of a wart on what could be a
consistent, general convention to put the type first always (even though I
don't follow my own preference).

DW
Jul 23 '05 #81
be****@pacbell.net wrote:
John Carson wrote:
"Steven T. Hatton" <ch********@germania.sup> wrote in message
news:yI********************@speakeasy.net
>
>> It is actually a prohibitive cost, because it means you can't
>> use libraries that use non-const references.
>
> No. It only means that you don't do it in *your* libraries. It's
> just silly to say you would never use other people's libraries
> because they don't conform you your coding conventions.
> Unfortunately established practices in C++ are very heterogeneous,
> and excluding libraries on the basis of failing to follow some
> established convention would probably exclude 90% of all C++ code
> _regardless_ of the convention used as a filter.


It is not silly at all. The point is that you want a cheap indicator of
what a function does. Just look at the function call and you know. Well,
if that is the sort of cursory study that is involved, how do you know if
the function is one of "yours" or one from some other library? Plainly
you can't know, so your cheap indicator is as likely to mislead as
inform. Sensible programmers will ignore it.


void Foo(int*);
void Foo(int&);

void A()
{
int x(0);
int& xx(x);

Foo(xx);
}

void B()
{
int y(0);
int* yy(&y);

Foo(yy);
}

Looking at these two functions, I don't see how it's any easier to see
that the call to Foo() in B() is likely to change y than it is to see
that the call to Foo() in A() will change x.

It's been my experience with large bodies of code that try to use
pointer arguments to signal "may change the argument" (e.g., Qt) is
that it simply doesn't work very well. The theory is that seeing the
"&" at the call site tells you it's a pointer, so you should be aware
that the pointee might change. My contrived example above that the call
site can be easily missing the "&", in which case you're no better off
than you would have been with a reference -- you have to read the
documentation.

A more realistic example of losing the "&" is when a function passes on
a pointer argument to another function:

void F(int* p)
{
...

G(p);

...
}

Bob


I agree. After this discussion started I began looking at places where
pointers are used, and, indeed, they can 'vanish' from clear sight. I
typically name things that are pointers _something_ptr, (intrusive)
reference counted pointers become _something_rptr and smart pointers become
_something_sptr.
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #82
"Steven T. Hatton" <ch********@germania.sup> wrote in message
news:kM********************@speakeasy.net

Yes, and I believe part of the OP's argument for using references over
pointers was that it reduces the need for detecting null pointers,
and thus results in more efficient code. I don't believe that
reasoning is viable.


As I remarked at another point in this thread:

If the client code uses pointers, then it doesn't make a lot of difference
if the function accepts pointers or references; the pointer is going to have
to be dereferenced by either the client (if the function takes references)
or the function (if the function takes pointers). The gain is when *neither*
client *nor* function uses pointers.

My practice is to use pointers rarely. On those rare occasions, I have a
heightened sense of danger and take extra care not to screw up.

It is worth pointing out that if you are a keen user of pointers, you will
typically be declaring and dereferencing them more often than just when
passing function arguments.

--
John Carson

Jul 23 '05 #83
John Carson wrote:
"Steven T. Hatton" <ch********@germania.sup> wrote in message
news:kM********************@speakeasy.net

Yes, and I believe part of the OP's argument for using references over
pointers was that it reduces the need for detecting null pointers,
and thus results in more efficient code. I don't believe that
reasoning is viable.


As I remarked at another point in this thread:

If the client code uses pointers, then it doesn't make a lot of difference
if the function accepts pointers or references; the pointer is going to
have to be dereferenced by either the client (if the function takes
references) or the function (if the function takes pointers). The gain is
when *neither* client *nor* function uses pointers.

My practice is to use pointers rarely. On those rare occasions, I have a
heightened sense of danger and take extra care not to screw up.

It is worth pointing out that if you are a keen user of pointers, you will
typically be declaring and dereferencing them more often than just when
passing function arguments.


Well, I would not make a habbit of dereferencing them to pass to functions I
write. I just pass the pointer.

TTTT, I've been all over the map on this issue. I like RAII. That means
"hard" member variables. I /can/ pass them by reference to anything that
doesn't try to keep an handle on them. But I don't find myself passing a
lot of data. I typically operate on it with member functions of the class
where it lives.
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #84
On Wed, 13 Jul 2005 12:31:29 +1000, "David White" <no@email.provided>
did courageously avow:
Steven T. Hatton wrote:
Phlip wrote:
void func(Objec const & object);

The const is after the Objec because that's where it _should_ be. The
notation 'const Objec &' is syntactic sugar with no other meaning
than 'Objec const &'. Type declarations should put the most
important part first.


http://www.research.att.com/~bs/bs_f...constplacement


Well, that's one opinion. I write the 'const' first as well, but only
because that's what almost everyone does, so I did too and now I'm used to
it. However, the form "int const" is more appealing because 'const' is just
a modifier and there can be many modifiers in a single declaration but only
one type. I like the consistency of the type always being first. I think
that putting 'const' in front of it is a bit of a wart on what could be a
consistent, general convention to put the type first always (even though I
don't follow my own preference).

DW


Isn't this more of a spiritual debate. I mean if you speak English
you ask the stable attendant for a brown horse. In French, a horse
brown, because of the syntax rules for the French language. In both
cases, the programmer/client, gets a horse and its color will be
brown. :=)

Ken Wilson

Amer. Dlx. Tele, Gary Moore LP, LP DC Classic w/P90s,
Jeff Beck Strat, Morgan OM Acoustic,
Rick 360/12, Std. Strat (MIM), Mesa 100 Nomad,
Mesa F-30

"Goodnight Austin, Texas, wherever you are."
Jul 23 '05 #85
Rick N. Backer wrote:
On Wed, 13 Jul 2005 12:31:29 +1000, "David White" <no@email.provided>
did courageously avow:
Steven T. Hatton wrote:
Phlip wrote:
void func(Objec const & object);

The const is after the Objec because that's where it _should_ be.
The notation 'const Objec &' is syntactic sugar with no other
meaning than 'Objec const &'. Type declarations should put the most
important part first.

http://www.research.att.com/~bs/bs_f...constplacement


Well, that's one opinion. I write the 'const' first as well, but only
because that's what almost everyone does, so I did too and now I'm
used to it. However, the form "int const" is more appealing because
'const' is just a modifier and there can be many modifiers in a
single declaration but only one type. I like the consistency of the
type always being first. I think that putting 'const' in front of it
is a bit of a wart on what could be a consistent, general convention
to put the type first always (even though I don't follow my own
preference).

DW


Isn't this more of a spiritual debate. I mean if you speak English
you ask the stable attendant for a brown horse. In French, a horse
brown, because of the syntax rules for the French language. In both
cases, the programmer/client, gets a horse and its color will be
brown. :=)


But in English do you write "horse brown" at one end of a sentence and
"brown horse" elsewhere?
1. int const * const * const p;
'p' is a const pointer to a const pointer to a const int.
(brown horse, brown horse, brown horse)

2. const int * const * const p;
'p' is a const pointer to a const pointer to an int const
(brown horse, brown horse, horse brown)

DW
Jul 23 '05 #86
Steven T. Hatton wrote:
Always use the weakest language construction with the fewest features.
This implies you should always use references unless you need a pointer's extra features.


And hope you never will need them.


Premature complexity is the root of all evil. I can change any part of my
program at whim, so I don't need to guess the future. If I ever need those
things, I change the reference to a pointer. Among other checks, I use as
much typesafety as possible, so the compiler will tell me if I missed any
dereferences.

If I am publishing an interface - if someone else might need a pointer - I
ought to write at least three reference applications for my library. They
should expose any needs.

--
Phlip
http://www.c2.com/cgi/wiki?ZeekLand
Jul 23 '05 #87
Rick N. Backer wrote:
Isn't this more of a spiritual debate?


#ifndef NDEBUG
# define FALLIBLE_INT Fallible<int> *
#else
typedef int * FALLIBLE_INT;
#endif

const FALLIBLE_INT q;

Oops. The programmer tried to create a pointer to an integer that checks its
validity. They want the checks to go away in Release mode.

In Debug mode, q points to a constant fallible int. In Release mode, q is a
constant pointer to an int. That's a silent error until something tries to
change the pointer in Release mode.

This can't break:

FALLIBLE_INT const q;

(Uncompiled code warning. If anyone finds an an issue with the example,
they'l be qualified to think of a similar one that generates the same
problem.)

--
Phlip
http://www.c2.com/cgi/wiki?ZeekLand
Jul 23 '05 #89
In message <db**********@nntp1.jpl.nasa.gov>, E. Robert Tisdale
<E.**************@jpl.nasa.gov> writes
Richard Herring wrote:
E. Robert Tisdale writes
Second, if your function must modify an object,
you should return a reference or pointer to that object:
//Object& func(const Object& object) {

Object& func(Object& object) {

// modify object
return object;
}
or
//Object* func(const Object* object) {

Object* func(Object* object) {

// modify *object
return object;
}
instead of void Ugh. I'd be more inclined to say,
"If your function modifies an object,
it MUST NOT return a reference to that object."
It just invites the reader to misinterpret what's going on.
If you write
f(a);
g(a);
it's obvious that the functions are not being called for their
return values, and therefore some side effect is intended.


But the same is true if you invoke

func(a);

You don't *need* to use the returned reference (pointer).


Of course. The fact that you don't use it is in itself a hint that
something else is going on. And if you don't use it, what's the point of
having it?
If you write
g(f(a));
or even
x = f(a);
it's not obvious to the reader that "a" is in effect used *twice*,
even though it only appears once.


Isn't it "obvious" that, in

std::cout << "i = " << 42 << std::endl;

ostream std::cout is used *thrice*?


It's "obvious" that the above looks nothing at all like a set of nested
function calls, so I don't see your point.
A function which does a single thing cleanly is usually preferable to
one which does two things, or which does the single thing obscurely.
Would you then agree that
a function should *not* modify two or more arguments?


I wouldn't make it an absolute rule, but if two data items are so
tightly coupled that it makes no sense to modify them separately, maybe
they should be encapsulated as some kind of structure.
so that you can use the function in an expression.

Which is only a benefit to authors of obfuscated code.


What's wrong with using functions in expressions?


Wrong question. You mean "What's wrong with using
functions-which-modify-their-arguments-and-also-return-them in
expressions?" and the answer is "it obfuscates the semantics."
If you are going to call one void function after another,
you might as well write your program in assembler.


I don't see why. The compiler does a much better job.

--
Richard Herring
Jul 23 '05 #90


Phlip wrote:
Rick N. Backer wrote:
Isn't this more of a spiritual debate?


#ifndef NDEBUG
# define FALLIBLE_INT Fallible<int> *
#else
typedef int * FALLIBLE_INT;
#endif

const FALLIBLE_INT q;

Oops. The programmer tried to create a pointer to an integer that checks its
validity. They want the checks to go away in Release mode.

In Debug mode, q points to a constant fallible int. In Release mode, q is a
constant pointer to an int. That's a silent error until something tries to
change the pointer in Release mode.

By using the '#define' macro, you're basically messing with the C++
type system and asking for trouble (in other places as well). Using
this instead:
#ifndef NDEBUG
typedef Fallible<int> * FALLIBLE_INT;
#else
typedef int * FALLIBLE_INT;
#endif
Now, p and q below are of the same type:

const FALLIBLE_INT p;
FALLIBLE_INT const q;

-shez-

Jul 23 '05 #91
E. Robert Tisdale wrote:
Richard Herring wrote:
E. Robert Tisdale writes
Second, if your function must modify an object,
you should return a reference or pointer to that object:
//Object& func(const Object& object) {

Object& func(Object& object) {

// modify object
return object;
}
or
//Object* func(const Object* object) {

Object* func(Object* object) {

// modify *object
return object;
}
instead of void


Ugh. I'd be more inclined to say,
"If your function modifies an object,
it MUST NOT return a reference to that object."
It just invites the reader to misinterpret what's going on.
If you write

f(a);
g(a);

it's obvious that the functions are not being called for their return
values, and therefore some side effect is intended.


But the same is true if you invoke

func(a);

You don't *need* to use the returned reference (pointer).
If you write

g(f(a));

or even

x = f(a);

it's not obvious to the reader that "a" is in effect used *twice*,
even though it only appears once.


Isn't it "obvious" that, in

std::cout << "i = " << 42 << std::endl;

ostream std::cout is used *thrice*?


Would that be written like this?

using namespace std;
cout.operator<<(cout.operator<<(cout.operator<<(co ut,i),42),endl);
In a mathematical context what you are showing may make sense using the
'move semantics' reasoning. To wit: "I don't care about the original
value." You could also do something like overload the call(s) so they take
either a const, or a non-const, and copy the const argument. But this is a
specialized area where RTFM/S is certainly a requirement.

You can do some nifty stuff when chaining together functors. Rather than
evaluating the operands as parameter expressions, you leave them
unevaluated, and hold on to them in the operator functor. You build up a
chain of functors, and let the optimizer have at it. Then you pull it all
out at once using a conversion operator on the outermost functor.... or
something like that. §22.4.7 TC++PL(SE). In the example Stroustrup shows,
he uses const references in both the parameter lists, and in the class
members.
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #92
Shezan Baig wrote:


Phlip wrote:
Rick N. Backer wrote:
> Isn't this more of a spiritual debate?
#ifndef NDEBUG
# define FALLIBLE_INT Fallible<int> *
#else
typedef int * FALLIBLE_INT;
#endif

const FALLIBLE_INT q;

Oops. The programmer tried to create a pointer to an integer that checks
its validity. They want the checks to go away in Release mode.

In Debug mode, q points to a constant fallible int. In Release mode, q is
a constant pointer to an int. That's a silent error until something tries
to change the pointer in Release mode.


That's because MACROS SUCK!

By using the '#define' macro, you're basically messing with the C++
type system and asking for trouble (in other places as well). Using
this instead:
#ifndef NDEBUG
typedef Fallible<int> * FALLIBLE_INT;
#else
typedef int * FALLIBLE_INT;
#endif
Now, p and q below are of the same type:

const FALLIBLE_INT p;
FALLIBLE_INT const q;

-shez-


We need a lot more of that kind of thinking around here.
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #93
Phlip wrote:
Steven T. Hatton wrote:
> Always use the weakest language construction with the fewest features.
> This implies you should always use references unless you need a pointer's > extra features.


And hope you never will need them.


Premature complexity is the root of all evil. I can change any part of my
program at whim, so I don't need to guess the future. If I ever need those
things, I change the reference to a pointer. Among other checks, I use as
much typesafety as possible, so the compiler will tell me if I missed any
dereferences.

If I am publishing an interface - if someone else might need a pointer - I
ought to write at least three reference applications for my library. They
should expose any needs.


Actually, that has the ring of truth to it. Unfortunately, at least for the
shortterm, I'm stuck with either expending a lot of effort to make
customized smart references, or I use pointers. Usually that means

osg::ref_ptr<T> t_rptr;

struct Klass {
// t_rptr_ reminds me I plan to keep a handle on the argument.
// The argument itself is a raw pointer.
Klass(T* t_rptr_):_t_rptr(t_rptr_) {}
private:
osg::ref_ptr<T> _t_rptr;
};

Klass K(t_rptr.get()); // get and pass the raw pointer held by t_rptr
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #94
On 2005-07-13 08:27:07 -0400, "Steven T. Hatton"
<ch********@germania.sup> said:
E. Robert Tisdale wrote:
Isn't it "obvious" that, in

std::cout << "i = " << 42 << std::endl;

ostream std::cout is used *thrice*?


Would that be written like this?

using namespace std;
cout.operator<<(cout.operator<<(cout.operator<<(co ut,i),42),endl);


No, like this:
cout.operator<<("i = ").operator<<(42).operator<<(endl);

--
Clark S. Cox, III
cl*******@gmail.com

Jul 23 '05 #95
In message <2005071311374316807%clarkcox3@gmailcom>, Clark S. Cox III
<cl*******@gmail.com> writes
On 2005-07-13 08:27:07 -0400, "Steven T. Hatton"
<ch********@germania.sup> said:
E. Robert Tisdale wrote:
Isn't it "obvious" that, in
std::cout << "i = " << 42 << std::endl;
ostream std::cout is used *thrice*?

Would that be written like this?
using namespace std;
cout.operator<<(cout.operator<<(cout.operator<<(co ut,i),42),endl);


No, like this:
cout.operator<<("i = ").operator<<(42).operator<<(endl);

That's comprehensible.
Try this:

Foo foo;
Bar bar;
Baz baz;
operator<<(operator<<(operator<<(cout, foo), bar), baz);

--
Richard Herring
Jul 23 '05 #96
On Wed, 13 Jul 2005 16:25:09 +1000, "David White" <no@email.provided>
did courageously avow:
Rick N. Backer wrote:
On Wed, 13 Jul 2005 12:31:29 +1000, "David White" <no@email.provided>
did courageously avow:
Steven T. Hatton wrote:
Phlip wrote:
> void func(Objec const & object);
>
> The const is after the Objec because that's where it _should_ be.
> The notation 'const Objec &' is syntactic sugar with no other
> meaning than 'Objec const &'. Type declarations should put the most
> important part first.

http://www.research.att.com/~bs/bs_f...constplacement

Well, that's one opinion. I write the 'const' first as well, but only
because that's what almost everyone does, so I did too and now I'm
used to it. However, the form "int const" is more appealing because
'const' is just a modifier and there can be many modifiers in a
single declaration but only one type. I like the consistency of the
type always being first. I think that putting 'const' in front of it
is a bit of a wart on what could be a consistent, general convention
to put the type first always (even though I don't follow my own
preference).

DW


Isn't this more of a spiritual debate. I mean if you speak English
you ask the stable attendant for a brown horse. In French, a horse
brown, because of the syntax rules for the French language. In both
cases, the programmer/client, gets a horse and its color will be
brown. :=)


But in English do you write "horse brown" at one end of a sentence and
"brown horse" elsewhere?
1. int const * const * const p;
'p' is a const pointer to a const pointer to a const int.
(brown horse, brown horse, brown horse)

2. const int * const * const p;
'p' is a const pointer to a const pointer to an int const
(brown horse, brown horse, horse brown)

DW

Fortunately no, English syntactical rules are a little tighter about
that then the syntax rules we're dealing with here. I think this is
why you see companies come up with those annoying coding guidelines,
so we spend less time busting each others chops over the nasty piece
of code they just wrote and more time actually producing something.
:-) There's nothing I like walking away from faster than a verbal
scuffle over formatting. You might as well discuss religion or
politics if that happens.

Ken Wilson

Amer. Dlx. Tele, Gary Moore LP, LP DC Classic w/P90s,
Jeff Beck Strat, Morgan OM Acoustic,
Rick 360/12, Std. Strat (MIM), Mesa 100 Nomad,
Mesa F-30

"Goodnight Austin, Texas, wherever you are."
Jul 23 '05 #97
Rick N. Backer wrote:
Fortunately no, English syntactical rules are a little tighter about
that then the syntax rules we're dealing with here. I think this is
why you see companies come up with those annoying coding guidelines,
so we spend less time busting each others chops over the nasty piece
of code they just wrote and more time actually producing something.
:-) There's nothing I like walking away from faster than a verbal
scuffle over formatting. You might as well discuss religion or
politics if that happens.

I have never found a need for a constant pointer, as opposed to a pointer to
constant.
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #98
Clark S. Cox III wrote:
On 2005-07-13 08:27:07 -0400, "Steven T. Hatton"
<ch********@germania.sup> said:
E. Robert Tisdale wrote:
Isn't it "obvious" that, in

std::cout << "i = " << 42 << std::endl;

ostream std::cout is used *thrice*?


Would that be written like this?

using namespace std;
cout.operator<<(cout.operator<<(cout.operator<<(co ut,i),42),endl);


No, like this:
cout.operator<<("i = ").operator<<(42).operator<<(endl);

That's what I started to write, and I suspect it will also work. Looks like
Java. :D
--
If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true.-Bertrand Russell
Jul 23 '05 #99
Shezan Baig wrote:
By using the '#define' macro, you're basically messing with the C++
type system and asking for trouble (in other places as well). Using
this instead:
Did you see the place where I wrote "If anyone finds an an issue with the
example, they'l be qualified to think of a similar one that generates the
same problem." ?

Steven T. Hatton wrote:
That's because MACROS SUCK!
Yet sometimes we pay our vendors to provide them.

My example is not the Alpha and Omega of 'const' placement. It merely shows
how const placement can't be called "_only_ a style question".
// t_rptr_ reminds me I plan to keep a handle on the argument.
I hate that kind of comment. There's no way for smart pointers to enforce
'new' (or have the Boosties found one?).

Rick N. Backer wrote:
Fortunately no, English syntactical rules are a little tighter about
that then the syntax rules we're dealing with here. I think this is
why you see companies come up with those annoying coding guidelines,
so we spend less time busting each others chops over the nasty piece
of code they just wrote and more time actually producing something.


This is why programmers should own tasks and share modules. As programmers
edit modules they should intentionally move them closer to community
agreement.

Coding guidelines are a sick attempt to enforce one benefit of teamwork,
without the other benefits. Like less bugs.

--
Phlip
http://www.c2.com/cgi/wiki?ZeekLand
Jul 23 '05 #100

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

Similar topics

7
by: winlinchu | last post by:
Hi! I use Python, and writing some extension modules I think which could be written an C compiler, useful only to compile extension modules (I not think an GCC!!!!), so that the user not have to...
29
by: Jim Hubbard | last post by:
Yet another hotfix alert (http://www.kbalertz.com/Feedback_823535.aspx) that states "To resolve this problem immediately, contact Microsoft Product Support Services to obtain the hotfix." ...
13
by: Bryan Parkoff | last post by:
You may notice that switch (...) is much faster than function that can gain a big improved performance because it only use JMP instruction however function is required to use CALL, PUSH, and POP...
25
by: dixie | last post by:
I have some code that adds new records into a table for each ID in a list box when a button on a form is clicked. This works fine. My problem now is that I wish to be able to edit all the records...
19
by: Raposa Velha | last post by:
Hello to all! Does any of you want to comment the approach I implement for instantiating a form? A description and an example follow. Cheers, RV jmclopesAThotmail.com replace the AT with the...
7
by: Alan Silver | last post by:
Hello, I would like to create a new web site with VWD, but would like to run it under IIS, not the development server. One reason for this is that I want the web site to be at the domain root,...
4
by: Pedro Leite | last post by:
Good Afternoon. the code below is properly retreiving binary data from a database and saving it. but instead of saving at client machine is saving at the server machine. what is wrong with my...
12
by: Paul H | last post by:
A little off topic this one because the database may not be written in Access. I am just looking for some advice.. I have an idea to help prevent a particular type of crime, a database will be...
32
by: andresj | last post by:
I was doing some programming in Python, and the idea came to my mind: using fractions instead of floats when doing 2/5. The problem arises when you try to represent some number, like 0.4 in a...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 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 former...

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.