Topic: Q: why references are constant references?


Author: Tom Payne <thp@cs.ucr.edu>
Date: 1997/09/11
Raw View
In comp.std.c++ Chris Waters <cwaters@systems.dhl.com> wrote:

: If operator[] returns a pointer, then that pointer has to be
: dereferenced.

Agreed.

: Even if it dereferenced implicitly, as above, it still
: invokes the copy constructor, which is unacceptable overhead.

Dereferencing turns a pointer into an lvalue for (i.e., reference to) the
pointer's referrent.  That involves no overhead, and from that point
on things proceed the same either way.

: And which doesn't work if operator[] is used as an rvalue.

If an lvalue or reference occurs in context that requires a
corresponding rvalue, automatic conversion takes place.  There's no
difference.

Tom Payne
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Solomon Foster <colomon@altair.com>
Date: 1997/09/02
Raw View
Tom Payne wrote:

> I completely agree, but I understand the rationale of those who preach
>
> against non-const reference parameters.  Their reasoning goes
> something like this.  When a maintenance programmer who comes from a C
>
> background sees an unadorned argument in a function call, he does not
> expect that argument to be modified.  So to avoid surprising him when
> he maintains a C++ program, we should pass modifiable arguments via
> pointers.  That way there will be a syntactic tip-off in the call,
> warning the programmer that this argument might be modified.  (I
> remain unconvinced.)

And there's good reason to be unconvinced:

    strcpy (string_a, string_b);

How does adding the lines

    void strcpy (string &a, string const &b);
.....
    string string_a;
    string string_b;

before the strcpy change things in the least?

Not to say I'd promote overloading C string library calls like that.
Just that any number of standard C idioms violate the above "rule".  Did
anyone ever propose the rule before C++ introduced call-by-reference?

Sol
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Mike Ferrel <mferrel@sr.hp.com>
Date: 1997/09/02
Raw View
Fergus Henderson wrote:
>
> Mark@mwilden.com writes:
>
>  >The usual case presented to support references isn't operator+=, it's
>  >operator[], so you can do
>  >
>  > container[x] = y;
>
> OK, so define
>
>         container[x]
>
> to be equivalent to
>
>         *(operator [] (x))
>
> That is, require the `operator []' function to return a pointer,
> and have the `container[x]' expression call the function and then
> dereference the pointer.
>
Of course, that's what the typical compiler already does, at the
code generation level.

The real problem is that since operator *(unary) is also overloadable,
what does "dereference the pointer" mean to you in such a context?

Operator * must produce an lvalue for your suggestion to work, but
if it produces a pointer which must then be magically dereferenced to
produce the needed lvalue, we get into an infinite dereference
recursion, or get back to where we started, the need for function
call expressions to be lvalues, AKA references.

Mike Ferrel
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Marcelo Cantos <marcelo@janus.mds.rmit.edu.au>
Date: 1997/09/04
Raw View
"Leo Goodstadt" <lg@mail.ndirect.co.uk> writes:

> Recently, I have started using the Microsoft Foundation Classes
> which tend to have a distinctive programming style.

Now there's an understatement!  All I can offer here is the advice
that MFC is _not_ an example of good object oriented design.
Borland's OWL has always been the better framework and _does_ pass
around const references.

> I find that it is very common to
> find functions like e.g.
>   void ScaleRectangle(CRect* rect)
> whereas I would tend to write
>   CRect ScaleRectangle(const CRect& rect)
> This means one often cannot write
>  CRect r = ScaleRectangle(RotateRectangle(GetRectangleFromSystem()));
> instead one finds
>  CRect r;
>  GetRectangleFromSystem(&r);
>  RotateRectangle(&r);
>  ScaleRectangle(&r);
> This is perhaps a slightly exaggerated example.

Not at all.  When I was still living in MFC (read loopy) land I had
this sort of rubbish all over my code, and I hated it!  Also, it took
me weeks to figure out how all my GDI objects were being freed (I
finally discovered MFC's idle loop -- truly bizarre).

> The question is does one get significant efficiency savings in terms
> of code size etc. from using the Microsoft style? How well can a
> compiler optimize out the object creation/assignations eg. for small
> objects such as "CRect"s or "CPoint"s which contain 4 or 2 ints.

There are absolutely no savings in passing pointers instead of
references (if anything, references have a slight edge due to fewer
aliasing problems).  Passing by value is definitely more expensive,
however it easily beats sticking them on the heap!  In any case, OWL
provides both forms (if I remember rightly): return by value, and
passing a non-const reference, so the user has the choice of syntactic
elegance or performance.

...
> Explicit and clear ownership patterns or the lack therof
> is one of the first things I notice when I encounter what are IMHO
> badly designed libraries (without naming names or pointing in the
> direction of Redmond :->)

I'm quite happy to name and point! ;-)

Cheers,
Marcelo

--
______________________________________________________________________
Marcelo Cantos, Research Assistant       __/_  marcelo@mds.rmit.edu.au
Multimedia Database Systems Group, RMIT   /       _ Tel 61-3-9282-2497
L2/723 Swanston St, Carlton VIC 3053, Aus/ralia ><_>Fax 61-3-9282-2490
Acknowledgements: errors - me; wisdom - God; sponsorship - RMIT
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: "Bill Wade" <bill.wade@stoner.com>
Date: 1997/09/08
Raw View
Leo Goodstadt <lg@mail.ndirect.co.uk> wrote in article
<01bcb8ba$f8b57280$LocalHost@lg>...
>
> > [deleted ] The rest of the code, for
> > the most part, should pass by reference or by value, depending on the
> > required semantics.  Passing by reference should almost always involve
> > passing a const reference.  More specifically, functions that
> > shouldn't mutate the passed object (which is the majority) should
> > accept a const reference or value argument.  Only those functions that
> > are specifically intended to change their arguments should accept
> > non-const arguments.
> >
> > Lastly, functions that do intend to change their arguments (ie: by
> > accepting reference arguments) should be named appropriately, so the
> > caller is fully aware that the object is going to modified by the
> > function (ie: call it setVariable() instead of f()).  This rule
> > doesn't apply to the extraction operator ('>>') since its
> > applicability to non-const reference arguments is a standard C++
> > paradigm.
> > Marcelo Cantos, Research Assistant       __/_  marcelo@mds.rmit.edu.au
>
> I would agree entirely. The above seems like common sense to me and has
> been the way I have been writing code for some years. However, have you
> ever encountered anything in a paper or an authoritative (i.e. quotable)
> source to this effect?

Const:
Meyers, Effective C++: "Use const whenever possible."

Functions changing arguments:
Stroustrup, TC++PL (2nd), p. 62: "However, to keep a program readable it is
in most cases best to avoid functions that modify their arguments."

>  I have tended to use pointers less and less often in function parameters
> and return types as opposed to references. Pointers in this context
> generally make most sense when dealing with heap objects. Passing objects
> using pointers I think runs the risk of obscuring objects ownership.

I tend to use pointers as parameters as an indication that the function
either:
  1) accepts NULL as an argument.
  2) Treats the argument as a C array (in which case I use [] in the
prototype).
Otherwise I prefer references (or value).  If you don't consider me to be
authoritative (I do ;-) there are some other opinions:

Stroustrup (on same page mentioned above) suggests that pointer parameters
are prefered for non-const arguments, because in the calling code it is
more obvious that the parameter is intended to be modified.  His example is
to prefer:
   inc(int* i){ ++(*i); }
to the reference version.  I prefer to try to make this clear in the
function name.  Stroustrup also makes the point that he tries to avoid
making this book be a style guide.

In "Large Scale C++ Software Design," Lakos suggests that arguments passed
by reference not be deleted, but otherwise I don't see an overall
philosophy on when to prefer references to pointers.  This seems like a
rare situation anyway.  Deleting an argument is much rarer than modifying
it.

For const arguments the syntactic sugar makes references preferable to
pointers, and examples are easy to find.
  DoSomethingWithConstString("foo");
vs.
  string temp("foo");
  DoSomethingWithConstString(&temp);
For non-const arguments authors seem much less willing to go on record
prefering
  ModifyFoo(foo);
to
  ModifyFoo(&foo);
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1997/09/08
Raw View
John Potter wrote:
>
> Marcelo Cantos <marcelo@janus.mds.rmit.edu.au> wrote:
> : Michael Corbeil <mcorbiel@worldnet.att.net> writes:
> [major snippage]
> : > I also don't see why references always should be passed as constants to
> : > methods.
> : I don't either.
> Hummm.
> [more snippage]
> : The reality is that raw pointers are very rare in application level
> : code.  They are an integral part of the language because they make it
> : easier to implement low level libraries.  This is where pointers
> : belong and where they are indeed essential.  The rest of the code, for
> : the most part, should pass by reference or by value, depending on the
> : required semantics.  Passing by reference should almost always involve
> : passing a const reference.  More specifically, functions that
> : shouldn't mutate the passed object (which is the majority) should
> : accept a const reference or value argument.  Only those functions that
> : are specifically intended to change their arguments should accept
> : non-const arguments.
>
> : Lastly, functions that do intend to change their arguments (ie: by
> : accepting reference arguments) should be named appropriately, so the
> : caller is fully aware that the object is going to modified by the
> : function (ie: call it setVariable() instead of f()).  This rule
> : doesn't apply to the extraction operator ('>>') since its
> : applicability to non-const reference arguments is a standard C++
> : paradigm.
>
> : Disclaimer -- It's late at night, so the above could be a load of
> : nonsense.  :-)
>
> Not at all.
>
> c++pl3e pg 163
> | 7.9 Advice
> | [1] Be suspicious of non-const reference arguments; if you want
> | the function to modify its arguments, use pointers and value
> | return instead.
>
> Playing devils advocate.  I have seen this elsewhere and am trying to
> understand it.
>
> Global variables are bad because there is no way to decide which
> functions may modify them short of looking at everything.  We might
> extend this to functions and their parameters in general.
>
> void f () {
>         int a;
>         f1(a);
>         f2(&a);
>         a = f3(a);
>         }
>
> Clearly, f3 results in a modification of 'a'.  It looks like f2 is
> likely to modify 'a' since it has it by C reference.  It does not look

No, f2 has not a by reference. It has a pointer to a.
And you should pray that f2 doesn't try to delete that pointer...
(or better, look into the documentation to find out - there
you'll find what is modified by f2, as well)

> like f1 will modify 'a' since it has it by C value.  If f1 actually
> has 'a' by const reference, there is no change.  But, if f1 has 'a' by
> non-const reference, the appearances may not be what happens.
>

Well, the "appearances" are what you expect from your *C*
experience. It's just your special bias.
Someone coming from FORTRAN will suspect *all* variables to change
(since FORTRAN parameters are per reference only). Someone coming
from Pascal will already be used to look at the function declaration
to find out if the function modifies its argument.
BTW, IMHO it's *very* good that you don't immediatly see if f1
changes a: If you don't know it, it means that you don't have a clue
what f1 is doing anyway. So you better look at it's documentation.
If you see immediatly from syntax that a might be changed, you
are less encouraged to check what the function actually does.

> You have suggested that functions which modify their parameters should
> have names which indicate that.  But what about functions with several
> parameters?  If this coding style is used, then it is clear from the
> call which parameters are going to be changed.  Pass by value and by
> reference (which is always const) look the same and assure no change,
> while pass by pointer looks different and assures change.
>

No, it is not at all clear which parameters are changed. What if
the routine called is really interested in the pointer itself,
not in the memory it points to?
There's no way to circumvent understanding what the function does.
So a style which does encourage not looking closer at it is not
favorable.

> It is a simple transformation of a function taking a non-const
> reference to one taking a pointer; however, the caller is now forced
> to know that the function will modify the parameter.
>         void f (X& r) { ... } ==> void f (X* p) { X& r(*p); ... }
> There should be no change in the generated code.
>

But there is a change in readability.
And there's another drawback: You cannot rely on a pointer being
nonnull. So you have to clobber your code with checks for NULL
(or trust your callers, who probably won't look up the documentation,
as syntax tells them all...)

> End devils advocate.
>
> This seems to say that in addition to never having a non-const
> reference, there should never be a pointer to const.
>         f1(X);        // ok value
>         f2(X const&); // ok efficient value
>         f3(X*);       // ok going to change it
Or going to delete it. Or just interested in the address.
>         f4(X&);       // not ok, looks like no change
Looks very much like a change.
>         f5(X const*); // not ok, looks like change
No, it's const.
But you forgot some:
          f6(X const*&);
This will *not* change the value, but might change the pointer itself.

>
> Can we expect the client of a function to be willing to use the extra
> character?  Better to get a compile time error than miss the function
> which produced the wrong value?
>

Better to look up the documentation that to rely on fuzzy
understanding (and if you don't know what might be changed by
the function, you *have* a fuzzy understanding of it)!

> Humm, does that justify _this_ being a pointer?
>

I think this is a pointer because at the time it was invented there
have not been any references.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1997/09/08
Raw View
William E. Kempf wrote:

[...]

> Someone else has already mentioned this technique in this thread.
> There's a problem with it.  C/C++ allows chaining of assignments.  How
> do you interpret this?
>
> int a = 1;
> int& b = a;
> int& p;
// references must be initialized
>
> &p = &b = &a;
>

Well, from the draft standard, it's quite obvious:

= is a right associative operator, so the whole thing must be
parsed as:

&p = (&b = &a)

So the reference b is reseated to the address of a, which also is
the result of the assignment expression, so p is reseated to the
address of a, as well.

This assignment rule would even be simple to define, by simply
saying for references the result of unary & is an lvalue.

But that doesn't mean that I would like it. It would make
references just a second syntax for pointers.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Chris Waters <cwaters@systems.dhl.com>
Date: 1997/09/10
Raw View
fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) writes:

> Marcelo Cantos <marcelo@janus.mds.rmit.edu.au> writes:
> >fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) writes:

> >> ... [references are not needed for `operator []', because you could]
> >> define

> >>  container[x]

> >> to be equivalent to

> >>  *(operator [] (x))

> >And exactly how is this supposed to benefit me?

> The idea is that the language would have been simpler if it only had pointers
> rather than having both pointers and references.

> I'm not seriously proposing this, I was just disagreeing with the
> argument that references were a _necessary_ extension in order to
> support user-defined operators.

If operator[] returns a pointer, then that pointer has to be
dereferenced.  Even if it dereferenced implicitly, as above, it still
invokes the copy constructor, which is unacceptable overhead.  And
which doesn't work if operator[] is used as an rvalue.  So, it seems
to me that references *were* a necessary extension.

The alternative is to have operator[] return a reference, but hide the
semantics.  The programmer sees only pointers and objects, but
internally, the system uses references where necessary and desirable.
What does this buy you?  Confusing semantics, and probably some
strange limitations on what you can do.  I don't think the language
would have been simpler.  At least, not in the sense of being easier
to understand.

Since this is c.s.c++, my suggestion is that we *not* submit a
proposal to remove references from the language!  :-)

cheers
--
Chris Waters             |
cwaters@systems.DHL.COM  |   pneumonoultra-      -osis is too long
xtifr@dsp.net (personal) | microscopicsilico-   to fit into a single
www.dsp.net/xtifr/ (web) |    volcaniconi-        standalone haiku.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Steve Clamage <stephen.clamage@Eng.Sun.COM>
Date: 1997/08/25
Raw View
Michael Corbeil wrote:
>
> You say there's a reason why C++ and C have pointers.  Well, I know the
> reason for C, however what is the real reason for C++?  Is it simply
> because it is an extension of C and the creator of C++ did not want to
> take the time to dig in to try to determine whether or not C++ really
> needed to support them; therefore, deciding to simply leave them as part
> of the newer language?

It is an explicit design goal of C++ to be "as close to C as
possible, but no closer."  Thus, C++ has pointers because C
does. If C++ did not have pointers, no useful C program
could be compiled as a C++ program. As it is, most well-written
C programs are also valid C++ programs, except for a few minor
things which are easily fixed.

> Also, regarding the question of "why references are constant references"
> seems a little odd, because references are not constant, at least not by
> default.  They have to be declared as constants in order to be
> constants.  If a reference is not declared or qualified as const, then
> it is not constant.

Evidently you have misunderstood something about const, or about
references, or perhaps both.

Regarding pointers, the pointer itself can be const or non-const,
and it can be declared to point to an object which is const or
non-const. All four possible combinations are allowed. If you
declare the pointer const, you cannot cause it to point to some
other object without violating some language rule.

References are in that sense always const. Like a const pointer,
you must initialize a reference to refer to some object at the
point where it is defined, and you cannot cause it to refer to a
different object without violating some language rule.

Also like a const pointer, a reference may be declared to
refer to a a const or non-const object. That is probably
what you were thinking of.

References were added to C++ because they were felt to be
genuinely useful, and some language features require references.
Pointers can be used when you want the possiblity of not
pointing at any object or when you want to point at different
objects at different times. References in C++ therefore are
defined to have the property that (short of violating some
language rule) they always refer to an object, and always
to the same object.

A reference is not the object, but refers to it. Implementations
commonly implement references exactly the same way as pointers.
The difference is not in the object model or generated code,
but in the way you are allowed to use references and pointers
in source code.

> I also don't see why references always should be passed as constants to
> methods.

There is no such rule.

> The one answer I know to this question is that passing a pointer will,
> at least generally, require much less stack space,

Not compared to references. The machine code whether using
pointers or references should be identical, except that
sometimes compilers can make more assumptions about
references, and generate better code.

> After having also repeatedly read how C is prone to memory leaks through
> the use of pointers, this all leads me to wonder why there is so much
> emphasis on passing a pointer to an object, such as a container, rather
> than passing it by reference.

Memory leaks are due to failure to properly deallocate an object,
and whether pointers or references are used is irrelevant. Using
garbage collection (not a standard C++ feature) solves the
problem of memory leaks.

> However, with pointers, I do have to admit that there is also the
> advantage of being able to create 'new' instances and delete them
> dynamically at runtime.

You can do that with references as well. Example:
 T& tref = *(new T); // T is some type
 ... // use the object via tref
 delete &tref;

--
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Marcelo Cantos <marcelo@janus.mds.rmit.edu.au>
Date: 1997/08/25
Raw View
Michael Corbeil <mcorbiel@worldnet.att.net> writes:

> You say there's a reason why C++ and C have pointers.  Well, I know the
> reason for C, however what is the real reason for C++?  Is it simply
> because it is an extension of C and the creator of C++ did not want to
> take the time to dig in to try to determine whether or not C++ really
> needed to support them; therefore, deciding to simply leave them as part
> of the newer language?

One of Stroustrup's primary design criteria was compatibility with C.
This is stress numerous times in the literature by the fact that every
program in _The C Programming Language_ is a valid C++ program.  If
this were the sole reason for the existence of pointers in C++ (and it
isn't) it would be sufficient.

> Also, regarding the question of "why references are constant references"
> seems a little odd, because references are not constant, at least not by
> default.  They have to be declared as constants in order to be
> constants.  If a reference is not declared or qualified as const, then
> it is not constant.

I think the point was that the reference itself, not the object it
references, is constant.  This is true, and tautologically so. 'A&' is
the same WRT const semantics as 'A* const', and 'const A&' is the same
as 'const A* const', hence a reference is always const.

> I also don't see why references always should be passed as constants to
> methods.

I don't either.

...
> The one answer I know to this question is that passing a pointer will,
> at least generally, require much less stack space, however is that
> really something that is a concern for most uses?

Less stack space than a reference argument?  I think not!

...
> After having also repeatedly read how C is prone to memory leaks through
> the use of pointers, this all leads me to wonder why there is so much
> emphasis on passing a pointer to an object, such as a container, rather
> than passing it by reference.

How is passing a heap object by reference going to reduce memory
leaks?  We reduce leaks by wrapping heap objects into classes, not by
debating the merits of references vs pointers.

> Again, I certainly understand that a pointer requires much less stack
> space than an object itself, however am not certain that it is something
> that mandates or requires so much emphasis.  Passing an object by
> reference seems perfectly logical or sensible from the conceptual point
> of view.

There appears to be some fundamental confusion here.  Passing by
reference does not, in any way shape or form, involve placing the
object on the call stack.  It is simply a syntactically more elegant
way of passing a pointer.  Semantically it is almost (but not quite)
identical.

You appear to be referring to pass by value semantics, which is
completely different from the other two semantics.

> The pointers only come into the scene at the lower level,
> platform and implementation point of view, I believe.  That is, at the
> design level, one shouldn't care how an object is passed to a method
> that will operate on it.  The design should only need to specify the
> ultimate purpose, I believe, though also needs to specify whether an
> argument to a method is constant, or not.

And in the real world we like to have some control over efficiency
which you seem to consider a mere quibble.  I assure you, it is not!

> Otherwise the OO design would
> not be strictly or directly portable to implementations where the OOPL
> doesn't have or support pointers, and if an application or system can be
> implemented in such a language, then, again, what's with this heavy
> emphasis on passing by pointer or by reference?

If the target language doesn't support the same semantics then it is
question begging to assume that it can perform the same job as C++ (or
at least, perform it as efficiently).

> It almost seems like
> it's straying from the ultimate objective and getting loaded down into
> possibly minor technicalities, having very little to no impact on the
> end user.

Ha!  We can serve up queries on a 12 gig SGML database in sub-second
times and our clients want it even faster!  You won't convince me that
the efficiencies inherent in the design C++ are "minor technicalities,
having very little to no impact on the end user".

> However, with pointers, I do have to admit that there is also the
> advantage of being able to create 'new' instances and delete them
> dynamically at runtime.

At do you consider this a minor technicality?

> I have no problems dealing or programming with pointers, at least in
> general, however have seen instances where passing an object that is to
> be modified by a method by reference seemed and was perfectly safe as
> well as very easy to understand.  The object was an instance of a
> template class that provided all the interface functionality required to
> manipulate the contents of an object of that class; therefore, even if
> the object could not entirely be deleted at runtime, at least not until
> the object using it was deleted, the entire contents could be deleted,
> which allowed unnecessarily used up memory to be freed.
>
> Finally, I certainly belive, at least when programming in C++, that
> there are definitely times when pointers and the new and delete
> operations need to be used.  However, I am not certain that references
> [always] need to be passed to methods as constants.  If someone who
> really understands this aspect of the teachings on how to program in C++
> could provide a sound explanation of this, it would be greatly
> appreciated.

The reality is that raw pointers are very rare in application level
code.  They are an integral part of the language because they make it
easier to implement low level libraries.  This is where pointers
belong and where they are indeed essential.  The rest of the code, for
the most part, should pass by reference or by value, depending on the
required semantics.  Passing by reference should almost always involve
passing a const reference.  More specifically, functions that
shouldn't mutate the passed object (which is the majority) should
accept a const reference or value argument.  Only those functions that
are specifically intended to change their arguments should accept
non-const arguments.

Lastly, functions that do intend to change their arguments (ie: by
accepting reference arguments) should be named appropriately, so the
caller is fully aware that the object is going to modified by the
function (ie: call it setVariable() instead of f()).  This rule
doesn't apply to the extraction operator ('>>') since its
applicability to non-const reference arguments is a standard C++
paradigm.

Disclaimer -- It's late at night, so the above could be a load of
nonsense.  :-)


--
______________________________________________________________________
Marcelo Cantos, Research Assistant       __/_  marcelo@mds.rmit.edu.au
Multimedia Database Systems Group, RMIT   /       _ Tel 61-3-9282-2497
L2/723 Swanston St, Carlton VIC 3053, Aus/ralia ><_>Fax 61-3-9282-2490
Acknowledgements: errors - me; wisdom - God; sponsorship - RMIT
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/08/27
Raw View
Steve Clamage <stephen.clamage@Eng.Sun.COM> writes:

>References were added to C++ because they were felt to be
>genuinely useful, and some language features require references.

The claim that some other language features -- in particular, operator
overloading -- required references has been often repeated, but I remain
unconvinced.  Operator overloading could have been supported with
adding references.  For example, it would have been possible to define

 x += y;

to be equivalent to

 operator += (&x, y);

rather than to

 operator += (x, y);

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/08/28
Raw View
Mark@mwilden.com writes:

 >Fergus Henderson wrote:
 >>
 >> Steve Clamage <stephen.clamage@Eng.Sun.COM> writes:
 >>
 >> >References were added to C++ because they were felt to be
 >> >genuinely useful, and some language features require references.
 >>
 >> The claim that some other language features -- in particular, operator
 >> overloading -- required references has been often repeated, but I remain
 >> unconvinced.  Operator overloading could have been supported with
 >> adding references.  For example, it would have been possible to define
 >>
 >>         x += y;
 >>
 >> to be equivalent to
 >>
 >>         operator += (&x, y);
 >>
 >> rather than to
 >>
 >>         operator += (x, y);
 >
 >The usual case presented to support references isn't operator+=, it's
 >operator[], so you can do
 >
 > container[x] = y;

OK, so define

 container[x]

to be equivalent to

 *(operator [] (x))

That is, require the `operator []' function to return a pointer,
and have the `container[x]' expression call the function and then
dereference the pointer.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Hyman Rosen <cardboard.mti.sgi.com!sgi.com!ncar.UCAR.EDU!uunet!jyacc!calumny!hymie>
Date: 1997/08/28
Raw View
fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) writes:
> Steve Clamage <stephen.clamage@Eng.Sun.COM> writes:
> >References were added to C++ because they were felt to be
> >genuinely useful, and some language features require references.
>
> The claim that some other language features -- in particular, operator
> overloading -- required references has been often repeated, but I remain
> unconvinced.

How do you propose implementing vector::operator[] without
references?
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Michael Corbeil <mcorbiel@worldnet.att.net>
Date: 1997/08/25
Raw View
You say there's a reason why C++ and C have pointers.  Well, I know the
reason for C, however what is the real reason for C++?  Is it simply
because it is an extension of C and the creator of C++ did not want to
take the time to dig in to try to determine whether or not C++ really
needed to support them; therefore, deciding to simply leave them as part
of the newer language?

Also, regarding the question of "why references are constant references"
seems a little odd, because references are not constant, at least not by
default.  They have to be declared as constants in order to be
constants.  If a reference is not declared or qualified as const, then
it is not constant.

I also don't see why references always should be passed as constants to
methods.  For example, if a method declares a bucket or container and
wants to call various methods to perform operations on the contents of
the container, such as to perform deletions, insertions, or updates on
the contents, then since the logic, when passing by reference, is both
easy to understand and sane, why is it so important or critical to pass
a pointer to the object?

The one answer I know to this question is that passing a pointer will,
at least generally, require much less stack space, however is that
really something that is a concern for most uses?  Will it cause a
program to fail under most circumstances?  I guess if the object or
container is very large, then it would certainly be more efficient to
pass a pointer.  However, I also have a feeling that the emphasis may,
at least in good part, be due to lower quality compilers.

As far as the efficiency impact on speed of performance, aren't
computers sufficiently powerful and packed with plenty of memory today
to basically make this a non-issue?

After having also repeatedly read how C is prone to memory leaks through
the use of pointers, this all leads me to wonder why there is so much
emphasis on passing a pointer to an object, such as a container, rather
than passing it by reference.

Again, I certainly understand that a pointer requires much less stack
space than an object itself, however am not certain that it is something
that mandates or requires so much emphasis.  Passing an object by
reference seems perfectly logical or sensible from the conceptual point
of view.  The pointers only come into the scene at the lower level,
platform and implementation point of view, I believe.  That is, at the
design level, one shouldn't care how an object is passed to a method
that will operate on it.  The design should only need to specify the
ultimate purpose, I believe, though also needs to specify whether an
argument to a method is constant, or not.  Otherwise the OO design would
not be strictly or directly portable to implementations where the OOPL
doesn't have or support pointers, and if an application or system can be
implemented in such a language, then, again, what's with this heavy
emphasis on passing by pointer or by reference?  It almost seems like
it's straying from the ultimate objective and getting loaded down into
possibly minor technicalities, having very little to no impact on the
end user.

However, with pointers, I do have to admit that there is also the
advantage of being able to create 'new' instances and delete them
dynamically at runtime.

I have no problems dealing or programming with pointers, at least in
general, however have seen instances where passing an object that is to
be modified by a method by reference seemed and was perfectly safe as
well as very easy to understand.  The object was an instance of a
template class that provided all the interface functionality required to
manipulate the contents of an object of that class; therefore, even if
the object could not entirely be deleted at runtime, at least not until
the object using it was deleted, the entire contents could be deleted,
which allowed unnecessarily used up memory to be freed.

Finally, I certainly belive, at least when programming in C++, that
there are definitely times when pointers and the new and delete
operations need to be used.  However, I am not certain that references
[always] need to be passed to methods as constants.  If someone who
really understands this aspect of the teachings on how to program in C++
could provide a sound explanation of this, it would be greatly
appreciated.


Mike Corbeil


William E. Kempf wrote:

> In article <01bc9ca5$cd262fa0$183374cf@worldnet.worldnet.att.net>,
>   "Cristian Georgescu" <Cristian.Georgescu@worldnet.att.net> wrote:
> >
> > About: Having references like pointers (and const references like
> const
> > pointers ...)
> >
> > > Now we have a construct IDENTICAL to pointers, except for the use
> of .
> > > instead of -> and & instead of *.  What's the point then?
> >
> > I must confess that I find a great convenience not to drag all over
> in the
> > user code the "pObj->member" versus "Obj.member" syntax and to use
> > uniformly the "refObj.member" versus "Obj.member" syntax.
> > That is, because if you finally want to change the "implementation"
> of a
> > pointer "pObj" to a 'real' object "Obj", then all the user code will
> have
> > to change! from: "pObj->member" to: "Obj.member". This will not
> happen with
> > variable references...!
>
> The necessity to search and replace -> with . is IMO a good thing.
> There are enough other differences between references and pointers
> that some searching and modifying of code is going to be necessary in
> almost every case where you'd change the type.  For instance, you
> can't delete a reference!  Nor can you cast a scalar to a reference
> (in order to "point" at a specific memory location!).  Nor can you do
> pointer arithmetic with references (and that's another one I'd like to
>
> see you find a syntactical way of doing).  There is a reason why C/C++
>
> has pointers.
>
> > > Such constructs are not as confusing when a language has only
> > > references, and not pointers.  If you have both, as C++ does, then
> the
> > > above code makes no sense what so ever.  I fail to see any other
> way
> > > to implement references, or how they would be a benefit in any
> other
> > > form.
> >
> > There is already a precedent in C++ with "struct" and "class" which
> in my
> > opinion:
> > "the existence of two such constructs is not as confusing when a
> language
> > has only structures, and not classes.  If you have both, as C++
> does, then
> > the
> > [...] it makes no sense what so ever."
> >
> > Well..., I blame it on compatibility with old C.
>
> There is only one difference between class and struct, and it is a
> subtle one at that.  I personally don't find this to be unclear or
> confusing.  You are right though, they both exist only for the
> compatibility with C.  There are also those that will argue that
> struct and class should not be the way they are (check out the latest
> C Users Journal).
>
> > Besides in the case of pointers there are some useful low-level
> techniques,
> > and I see them well in implementation code but not in ADT code.
>
> C++ is meant to be close to the machine level (at least in terms of
> speed and capability).  This is both its strength and its weakness.
> However, I don't think it should be made any higher level.  We have
> other languages (such as Java) for that.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Tom Payne <thp@cs.ucr.edu>
Date: 1997/08/28
Raw View
In comp.std.c++ Fergus Henderson <fjh@mundook.cs.mu.OZ.AU> wrote:
: Mark@mwilden.com writes:
[...]
:  >The usual case presented to support references isn't operator+=, it's
:  >operator[], so you can do
:  >
:  > container[x] = y;

: OK, so define

:  container[x]

: to be equivalent to

:  *(operator [] (x))

: That is, require the `operator []' function to return a pointer,
: and have the `container[x]' expression call the function and then
: dereference the pointer.


So exactly who is doing the dereferencing the result here, if
operator[] returns a pointer?  (I think of the expression container[x]
as denoting the result obtained by applying operator[] to container
and x.)

Tom Payne
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: marcsh@corel.ca (Marc Sherman)
Date: 1997/08/28
Raw View
>In comp.std.c++ Fergus Henderson <fjh@mundook.cs.mu.OZ.AU> wrote:
[snip]
>: That is, require the `operator []' function to return a pointer,
>: and have the `container[x]' expression call the function and then
>: dereference the pointer.

In article <5u4ke7$6io$1@skylark.ucr.edu>, Tom Payne <thp@cs.ucr.edu>
wrote:
>So exactly who is doing the dereferencing the result here, if
>operator[] returns a pointer?  (I think of the expression container[x]
>as denoting the result obtained by applying operator[] to container
>and x.)

There's already precedence for operator expressions doing more than just
calling the appropriate operator overload function.  For example, the
delete expression:
     delete t;
is the same as the code:
     t->~T; T::operator delete(t);

Fergus's "proposal" would have the the [] expression:
     x[i] = y;
produce the same assembly as:
     *(::operator[](&x, i)) = y;

- Marc
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Mark@mWilden.com
Date: 1997/08/28
Raw View
Fergus Henderson wrote:
>
> OK, so define
>
>         container[x]
>
> to be equivalent to
>
>         *(operator [] (x))
>
> That is, require the `operator []' function to return a pointer,
> and have the `container[x]' expression call the function and then
> dereference the pointer.

I'm not sure I quite follow, but are you saying make it a "special"
operator (like operator->()) that does more than just return a value,
i.e. it must return a value and additionally dereference that value?

Of course, requiring operator[] to return a pointer would make its use
less flexible than letting it return any old thing it wants, which is
certainly an argument against it. For example, you'd be unable to return
a temporary object, if that was your desire.

It seems to me that in this case, at least, using references simplifies
the language.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Marcelo Cantos <marcelo@janus.mds.rmit.edu.au>
Date: 1997/08/29
Raw View
fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) writes:

>  >The usual case presented to support references isn't operator+=, it's
>  >operator[], so you can do
>  >
>  > container[x] = y;
>
> OK, so define
>
>  container[x]
>
> to be equivalent to
>
>  *(operator [] (x))

And exactly how is this supposed to benefit me?


--
______________________________________________________________________
Marcelo Cantos, Research Assistant       __/_  marcelo@mds.rmit.edu.au
Multimedia Database Systems Group, RMIT   /       _ Tel 61-3-9282-2497
L2/723 Swanston St, Carlton VIC 3053, Aus/ralia ><_>Fax 61-3-9282-2490
Acknowledgements: errors - me; wisdom - God; sponsorship - RMIT
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Mark@mWilden.com
Date: 1997/08/29
Raw View
I believe in using const references for builtin types, for the reasons
usually stated (that it makes clear at the point of call whether the
value will be modified). But I've stopped using them for user-defined
types. For example:

 struct S {
    double Calc() const { return val; }
 private:
    double val;
 // ...
 };

 double foo(const S& s)
 {
    return s.Calc();
 }

All well and good. But let's say that S::Calc() changes such that it
computes and stores val and must be changed to nonconst. You then have
to hunt down every place that S::Calc() is called to make sure it isn't
being called on a const. There is a (to me) undesirable dependency set
up here between S::Calc() and all objects on which it is called. And for
what?

By just doing

 double foo(S& s)
 {
    return s.Calc();
 }

you just let S::Calc do its thing. It seems to me that in this case
making s const involves S::Calc()'s clients needing to be aware of the
implementation of S::Calc().
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Jason Merrill <jason@cygnus.com>
Date: 1997/08/31
Raw View
>>>>> Mark  <Mark@mWilden.com> writes:

> All well and good. But let's say that S::Calc() changes such that it
> computes and stores val and must be changed to nonconst. You then have
> to hunt down every place that S::Calc() is called to make sure it isn't
> being called on a const.

When you change your API, users often have to change.  If you change Calc
such that it now changes the value of S, that's a pretty large change.  If
Calc performs an action that does not actually change the conceptual value
of S, even if it modifies the internal data for caching or whatever, the
function can remain const.  That's what mutable is for.

Jason
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Gerard Weatherby <gerardw@alum.mit.edu>
Date: 1997/08/31
Raw View
Mark@mWilden.com wrote:
...
> All well and good. But let's say that S::Calc() changes such that it
> computes and stores val and must be changed to nonconst. You then have
> to hunt down every place that S::Calc() is called to make sure it isn't
> being called on a const. There is a (to me) undesirable dependency set
> up here between S::Calc() and all objects on which it is called. And for
> what?

Whether S::Calc( ) is const or not should depend on the logical
interface the class presents to it's client, not bitwise constness.  The
storage for "val" can be made mutable if added later. (Alternatively,
this can be const_cast.)
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/09/01
Raw View
Marcelo Cantos <marcelo@janus.mds.rmit.edu.au> writes:

>fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) writes:
>
>> ... [references are not needed for `operator []', because you could]
>> define
>>
>>  container[x]
>>
>> to be equivalent to
>>
>>  *(operator [] (x))
>
>And exactly how is this supposed to benefit me?

The idea is that the language would have been simpler if it only had pointers
rather than having both pointers and references.

I'm not seriously proposing this, I was just disagreeing with the
argument that references were a _necessary_ extension in order to
support user-defined operators.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: spam.kill.srwillrd@novia.net (William E. Kempf)
Date: 1997/08/04
Raw View
In article <01bc9ca5$cd262fa0$183374cf@worldnet.worldnet.att.net>,
  "Cristian Georgescu" <Cristian.Georgescu@worldnet.att.net> wrote:
>
> About: Having references like pointers (and const references like const
> pointers ...)
>
> > Now we have a construct IDENTICAL to pointers, except for the use of .
> > instead of -> and & instead of *.  What's the point then?
>
> I must confess that I find a great convenience not to drag all over in the
> user code the "pObj->member" versus "Obj.member" syntax and to use
> uniformly the "refObj.member" versus "Obj.member" syntax.
> That is, because if you finally want to change the "implementation" of a
> pointer "pObj" to a 'real' object "Obj", then all the user code will have
> to change! from: "pObj->member" to: "Obj.member". This will not happen with
> variable references...!

The necessity to search and replace -> with . is IMO a good thing.
There are enough other differences between references and pointers
that some searching and modifying of code is going to be necessary in
almost every case where you'd change the type.  For instance, you
can't delete a reference!  Nor can you cast a scalar to a reference
(in order to "point" at a specific memory location!).  Nor can you do
pointer arithmetic with references (and that's another one I'd like to
see you find a syntactical way of doing).  There is a reason why C/C++
has pointers.

> > Such constructs are not as confusing when a language has only
> > references, and not pointers.  If you have both, as C++ does, then the
> > above code makes no sense what so ever.  I fail to see any other way
> > to implement references, or how they would be a benefit in any other
> > form.
>
> There is already a precedent in C++ with "struct" and "class" which in my
> opinion:
> "the existence of two such constructs is not as confusing when a language
> has only structures, and not classes.  If you have both, as C++ does, then
> the
> [...] it makes no sense what so ever."
>
> Well..., I blame it on compatibility with old C.

There is only one difference between class and struct, and it is a
subtle one at that.  I personally don't find this to be unclear or
confusing.  You are right though, they both exist only for the
compatibility with C.  There are also those that will argue that
struct and class should not be the way they are (check out the latest
C Users Journal).

> Besides in the case of pointers there are some useful low-level techniques,
> and I see them well in implementation code but not in ADT code.

C++ is meant to be close to the machine level (at least in terms of
speed and capability).  This is both its strength and its weakness.
However, I don't think it should be made any higher level.  We have
other languages (such as Java) for that.

-----
William E. Kempf          : http://www.novia.net/~srwillrd
"Sir Willard"             : mailto:srwillrd@novia.net (home)
Knight of the Ascii Table :
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: spam.kill.srwillrd@novia.net (William E. Kempf)
Date: 1997/08/04
Raw View
In article <01bc9cb7$be46f200$183374cf@worldnet.worldnet.att.net>,
  "Cristian Georgescu" <Cristian.Georgescu@worldnet.att.net> wrote:
>
> William E. Kempf <spam.kill.srwillrd@novia.net> wrote in article
> <340b49d0.616665678@news.novia.net>...
> > "Cristian Georgescu" <Cristian.Georgescu@worldnet.att.net> wrote:
> >
> > :In C++ the references are const (after initialization cannot be
> changed).
> > :Is there a reason for not having also "variable" references (like in
> Java
> > :f.i.)?
> > :
> > How would you assign the reference to something else?
> >
> > int a = 1;
> > int b = 2;
> > int& i = a;
> >
> > i = b; // This assigns the value, not the reference!
> > i = &b; // Can't assign a pointer to a int reference!
> >
> > Making case 2 work (meaning make the compiler treat this as proper
> > syntax, assuming this is a reference reasignment) would cause
> > confusion.  Why syntax differences between initialization and
> > assignment?  In other words:
> >
> > int& i = b;
> > i = &b;  // Why are they different?!
> >
> > So let's make them the same:
> >
> > int& i = &b;
> > i = &b;
> > SomeFunc(&b); // It expects a reference!
>
> You make a good point here. But then, what about the idea of using &i = &b
> for re-binding a reference:
>
>     int a = 1;
>     int b = 2;
>     int& r = a;   // Initialise reference r to variable a
>
>      r =  b; // This assigns the value, not the reference! (same as init)
>     &r = &b;      // Re-bind the reference
>
>     int a = 1;
>     int b = 2;
>     int* p = &a;  // Initialise pointer p to address of variable a
>
>     *p =  b; // This assigns the value
>      p = &b;      // Re-bind the pointer to address of variable a (same as
> init)
>

Someone else has already mentioned this technique in this thread.
There's a problem with it.  C/C++ allows chaining of assignments.  How
do you interpret this?

int a = 1;
int& b = a;
int& p;

&p = &b = &a;

Someone more knowledgeable about compiler design may show me wrong,
but I don't see how the compiler can successfully interpret &b in the
above, since it is both a RHS and a LHS argument.

> However, there may be a simpler solution:
> One can let the r1=r2 syntax always mean "assign through r1 to the object
> referred to" (when r2 is an object as well as when r2 is a reference) and
> for re-binding r1, one can use something like:
>
>     SetRef r1 = r2;  // again r2 can be an either object or a reference
>
> This is clean and should not create any problems (The only inconvenience
> would be the introduction of another keyword).

It goes beyond just adding a new key word.  What is SetRef?  Doesn't
look like it's an operator.  It's definately not a function.  It is
outside of the syntax of C++.

Maybe you could change it to:

r1 SetRef r2;  // Actually, the committee would prolly make it setref

This would work, and SetRef (setref) could be an operator, much like
sizeof is.  Still seems like a waste to me, as this just makes a
reference a pretty pointer.  The biggest example of why I think this
is ugly in comparison to the mixed pointer/reference we have in C++ is
when passing constant references.  The reason to do so is to prevent
temporary object creation, yet prevent the user from modifying the
data.  If we can "re-point" a reference we'd have to use syntax like
this:

void func(const SomeObj & const ref)   // constant ref to constant
SomeObj

Sure it works, but it is definately uglier and less convenient then
what we have today.

-----
William E. Kempf          : http://www.novia.net/~srwillrd
"Sir Willard"             : mailto:srwillrd@novia.net (home)
Knight of the Ascii Table :
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: "Cristian Georgescu" <Cristian.Georgescu@worldnet.att.net>
Date: 1997/07/29
Raw View
In C++ the references are const (after initialization cannot be changed).
Is there a reason for not having also "variable" references (like in Java
f.i.)?

Of course that this would overlap semantically with pointers but references
are more convenient (and anyhow const pointers already overlap semantically
with the actual references...).

I see no reason why the language would not have references that can be
reassigned to different variables during their lifetime, and reserve const
references for the usage that they have now.

     _________________________________________________
     Cristian Georgescu

     Work         Smith Industries
     address:     Aerospace & Defense Systems
                  7-9 Vreeland Road,
                  Florham Park, NJ 07932, USA.

     E-mail:      Georgescu_Christian@si.com

     tel:         1 (201) 822-1300 / 2229

     tel:         1 (212) 753-8736
     _________________________________________________

---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Tom Payne <thp@cs.ucr.edu>
Date: 1997/07/29
Raw View
In comp.std.c++ Cristian Georgescu <Cristian.Georgescu@worldnet.att.net> wrote:
: In C++ the references are const (after initialization cannot be changed).
: Is there a reason for not having also "variable" references (like in Java
: f.i.)?

: Of course that this would overlap semantically with pointers but references
: are more convenient (and anyhow const pointers already overlap semantically
: with the actual references...).

: I see no reason why the language would not have references that can be
: reassigned to different variables during their lifetime, and reserve const
: references for the usage that they have now.

In D&E, p.86, Stroustrup writes:

  I had in the past been bitten by Algol68 references where r1=r2 can
  either assign through r1 to the object referred to or assign a new
  references value to r1 (re-binding r1) depending on the type of r2.
  I wanted to avoid such problems in c++.

Tom Payne
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: spam.kill.srwillrd@novia.net (William E. Kempf)
Date: 1997/07/30
Raw View
"Cristian Georgescu" <Cristian.Georgescu@worldnet.att.net> wrote:

:In C++ the references are const (after initialization cannot be changed).
:Is there a reason for not having also "variable" references (like in Java
:f.i.)?
:
:Of course that this would overlap semantically with pointers but references
:are more convenient (and anyhow const pointers already overlap semantically
:with the actual references...).

No it wouldn't.  There are still differences between pointers and
references beyond whether they can be reassigned.  For instance, you
can delete on a constant pointer, but not on a reference.

:I see no reason why the language would not have references that can be
:reassigned to different variables during their lifetime, and reserve const
:references for the usage that they have now.

How would you assign the reference to something else?

int a = 1;
int b = 2;
int& i = a;

i = b; // This assigns the value, not the reference!
i = &b; // Can't assign a pointer to a int reference!

Making case 2 work (meaning make the compiler treat this as proper
syntax, assuming this is a reference reasignment) would cause
confusion.  Why syntax differences between initialization and
assignment?  In other words:

int& i = b;
i = &b;  // Why are they different?!

So let's make them the same:

int& i = &b;
i = &b;
SomeFunc(&b); // It expects a reference!

And what about a reference that is truly const in your world?  Define
it like this?

const int & const i;

Now we have a construct IDENTICAL to pointers, except for the use of .
instead of -> and & instead of *.  What's the point then?

Such constructs are not as confusing when a language has only
references, and not pointers.  If you have both, as C++ does, then the
above code makes no sense what so ever.  I fail to see any other way
to implement references, or how they would be a benefit in any other
form.

-----
William E. Kempf          : http://www.novia.net/~srwillrd
"Sir Willard"             : mailto:srwillrd@novia.net (home)
Knight of the Ascii Table :
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "Paul D. DeRocco" <pderocco@ix.netcom.crud.com>
Date: 1997/07/30
Raw View
Cristian Georgescu wrote:
>
> In C++ the references are const (after initialization cannot be changed).
> Is there a reason for not having also "variable" references (like in Java
> f.i.)?
>
> Of course that this would overlap semantically with pointers but references
> are more convenient (and anyhow const pointers already overlap semantically
> with the actual references...).
>
> I see no reason why the language would not have references that can be
> reassigned to different variables during their lifetime, and reserve const
> references for the usage that they have now.

With pointers, the name represents the address, and an operator is used
to look through the address to whatever is pointed to. With references,
the name refers to the thing referred to, and there is no way to
represent the address. The only way I can see to do it would be to make
the unary & operator produce an lvalue when applied to a reference:

 int x, y;
 int &r = x; // initialize reference

 &r = y;     // change reference

but this would introduce a situation where &r would be an lvalue in some
cases but not in others. Ugh.

I find the fact that references can't be redirected to be one of their
main virtues.

--

Ciao,
Paul

(Please remove the extra "crud" from the return address,
which has been altered to foil junk mail senders.)
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: antispam.icedancer@antispam.ibm.net (Ken Walter)
Date: 1997/07/30
Raw View
In message <01bc9bba$d7e89ea0$f43474cf@worldnet.worldnet.att.net> - "Cristian
Georgescu" <Cristian.Georgescu@worldnet.att.net>29 Jul 97 06:06:33 GMT writes:

[...]

 I see no reason why the language would not have references that can be
 reassigned to different variables during their lifetime, and reserve const
 references for the usage that they have now.

It is possible, take a look at Algol68.
Since references are automatically dereferenced you would need
other operators to assign and compare references.

But then you wouldn't need "->".





Ken Walter     (Remove antispam. from address)
All the above is hearsay and the opinion of no one in particular.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: "Cristian Georgescu" <Cristian.Georgescu@worldnet.att.net>
Date: 1997/07/31
Raw View
Tom Payne <thp@cs.ucr.edu> wrote in article
<5rl4nq$bvg$1@skylark.ucr.edu>...
> In comp.std.c++ Cristian Georgescu <Cristian.Georgescu@worldnet.att.net>
wrote:
> : In C++ the references are const (after initialization cannot be
changed).
> : Is there a reason for not having also "variable" references (like in
Java
> : f.i.)?
>
> : Of course that this would overlap semantically with pointers but
references
> : are more convenient (and anyhow const pointers already overlap
semantically
> : with the actual references...).
>
> : I see no reason why the language would not have references that can be
> : reassigned to different variables during their lifetime, and reserve
const
> : references for the usage that they have now.
>
> In D&E, p.86, Stroustrup writes:
>
>   I had in the past been bitten by Algol68 references where r1=r2 can
>   either assign through r1 to the object referred to or assign a new
>   references value to r1 (re-binding r1) depending on the type of r2.
>   I wanted to avoid such problems in c++.
>
> Tom Payne
> ---

I understand that this may be annoying. However one can let the r1=r2
syntax always mean "assign through r1 to the object referred to" (when r2
is an object as well as when r2 is a reference) and for re-binding r1, one
can use something like:

    SetRef r1 = r2;  // again r2 can be an either object or a reference

This is clean and should not create any problems (The only inconvenience
would be the introduction of another keyword).

I must confess that I find a great convenience not to drag all over in the
user code the "pObj->member" versus "Obj.member" syntax and to use
uniformly the "refObj.member" versus "Obj.member" syntax.
That is, because if you finally want to change the "implementation" of a
pointer "pObj" to a 'real' object "Obj", then all the user code will have
to change! from: "pObj->member" to: "Obj.member". This will not happen with
variable references...!

---

In Basic (yes, in Basic and I know that this will be considered a remark of
bas taste but ...) there are two syntaxes:

    Let r1=r2

equivalent to:

    r1=r2

and:

    Set r1=r2

for re-binding r1 to either r2 (if r2 is an objent) or to the object
refered by r2 (if r2 is a reference).

---

And, maybe even the introduction of a new keywork can be avoided addmiting
to take the address of a reference and saying that the address of a
reference is a reference; then, the re-binding could be done by writing
something like:

    r1 = &r2;  // re-binding r1 (and the address of a reference is a
reference)

instead of:

    SetRef r1 = r2;

     _________________________________________________
     Cristian Georgescu

     Work         Smith Industries
     address:     Aerospace & Defense Systems
                  7-9 Vreeland Road,
                  Florham Park, NJ 07932, USA.

     E-mail:      Georgescu_Christian@si.com

     tel:         1 (201) 822-1300 / 2229
     .................................................
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "Cristian Georgescu" <Cristian.Georgescu@worldnet.att.net>
Date: 1997/07/31
Raw View
About: Having references like pointers (and const references like const
pointers ...)

> Now we have a construct IDENTICAL to pointers, except for the use of .
> instead of -> and & instead of *.  What's the point then?

I must confess that I find a great convenience not to drag all over in the
user code the "pObj->member" versus "Obj.member" syntax and to use
uniformly the "refObj.member" versus "Obj.member" syntax.
That is, because if you finally want to change the "implementation" of a
pointer "pObj" to a 'real' object "Obj", then all the user code will have
to change! from: "pObj->member" to: "Obj.member". This will not happen with
variable references...!

> Such constructs are not as confusing when a language has only
> references, and not pointers.  If you have both, as C++ does, then the
> above code makes no sense what so ever.  I fail to see any other way
> to implement references, or how they would be a benefit in any other
> form.

There is already a precedent in C++ with "struct" and "class" which in my
opinion:
"the existence of two such constructs is not as confusing when a language
has only structures, and not classes.  If you have both, as C++ does, then
the
[...] it makes no sense what so ever."

Well..., I blame it on compatibility with old C.

Besides in the case of pointers there are some useful low-level techniques,
and I see them well in implementation code but not in ADT code.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "Cristian Georgescu" <Cristian.Georgescu@worldnet.att.net>
Date: 1997/07/31
Raw View
William E. Kempf <spam.kill.srwillrd@novia.net> wrote in article
<340b49d0.616665678@news.novia.net>...
> "Cristian Georgescu" <Cristian.Georgescu@worldnet.att.net> wrote:
>
> :In C++ the references are const (after initialization cannot be
changed).
> :Is there a reason for not having also "variable" references (like in
Java
> :f.i.)?
> :
> How would you assign the reference to something else?
>
> int a = 1;
> int b = 2;
> int& i = a;
>
> i = b; // This assigns the value, not the reference!
> i = &b; // Can't assign a pointer to a int reference!
>
> Making case 2 work (meaning make the compiler treat this as proper
> syntax, assuming this is a reference reasignment) would cause
> confusion.  Why syntax differences between initialization and
> assignment?  In other words:
>
> int& i = b;
> i = &b;  // Why are they different?!
>
> So let's make them the same:
>
> int& i = &b;
> i = &b;
> SomeFunc(&b); // It expects a reference!

You make a good point here. But then, what about the idea of using &i = &b
for re-binding a reference:

    int a = 1;
    int b = 2;
    int& r = a;   // Initialise reference r to variable a

     r =  b; // This assigns the value, not the reference! (same as init)
    &r = &b;      // Re-bind the reference


    int a = 1;
    int b = 2;
    int* p = &a;  // Initialise pointer p to address of variable a

    *p =  b; // This assigns the value
     p = &b;      // Re-bind the pointer to address of variable a (same as
init)



However, there may be a simpler solution:
One can let the r1=r2 syntax always mean "assign through r1 to the object
referred to" (when r2 is an object as well as when r2 is a reference) and
for re-binding r1, one can use something like:

    SetRef r1 = r2;  // again r2 can be an either object or a reference

This is clean and should not create any problems (The only inconvenience
would be the introduction of another keyword).
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]