bs@alice.UucP (Bjarne Stroustrup) (09/06/86)
Karl W. Z. Heuer writes: > BMS-AT!stuart writes: > >[re the declaration of reference types "foo(char &c)"] > >I don't like this. It violates the nice consistent way that C expressions > >work. 'char *c' means that '*c' is of type char. '&c' is not of type > >char in any other context. > > I am also somewhat uneasy about calling it "char &c". The consistent way to > declare it would be "char *&c", since you have to write "&c" to get ahold of > the "char *" object you are really using. The notation T& is the C++ notation for a reference to an object of type T. char& c; declares c to be a reference to a char char*& r; declares r to be a reference to a char* & is a declarator operator exactly like *
ark@alice.UucP (Andrew Koenig) (09/07/86)
Karl W. Z. Heuer writes: > BMS-AT!stuart writes: > >[re the declaration of reference types "foo(char &c)"] > >I don't like this. It violates the nice consistent way that C expressions > >work. 'char *c' means that '*c' is of type char. '&c' is not of type > >char in any other context. > > I am also somewhat uneasy about calling it "char &c". The consistent way to > declare it would be "char *&c", since you have to write "&c" to get ahold of > the "char *" object you are really using. Bjarne Stroustrup made a comment on this about the way C++ does things, but I suspect his remark is a little too abbreviated for people not familiar with C++. Here is some more detail: In C++ one can declare a reference using the & declarator operator in much the same way as one can declare a pointer using the * declarator operator. There is one big difference: a reference MUST always be initialized at the time it is declared. Thus, I can write: char c; char &cr = c; char *cp = &c; The first example declares a character. No problem there. The third declares a character pointer and initializes it to the address of c. No problem there either. The second line declares a character reference named cr and makes it a synonym for c. Thus, if I write *cp = '?'; that sets the value of c to '?'; and so does cr = '?'; You can see a few things from this example: 1. A reference must always be initialized as it is delcared. 2. Subsequent uses of the reference denote the object with which the reference was initialized. 3. Therefore, the initializer for a reference must be an lvalue. In other words: char c; char &cr = c; /* legal */ char &cr; /* illegal -- no initialization */ char &cr = &c; /* illegal -- &c is not an lvalue */
sam@think.COM (Sam Kendall) (09/09/86)
In article <6027@alice.uUCp> ark@alice.UucP (Andrew Koenig) writes: > 1. A reference must always be initialized as it is delcared. Except of course for formal arguments, which are initialized by their actuals. > 3. Therefore, the initializer for a reference must be an lvalue. C++ Ref Man 3.6.3: If the initializer for a reference to type T is not an lvalue an object of type T will be created and initialized with the initializer. The reference then becomes a name for that object. This is also the semantics of Fortran argument passing, and I'm sure people calling Fortran from C++ are very happy -- `sin(2.3)', if `sin' is a Fortran function, works! > char c; > char &cr = &c; /* illegal -- &c is not an lvalue */ The last line is illegal because `&c' has the wrong type, not because it is an rvalue. --- Sam Kendall sam@Think.COM Thinking Machines Corp. ihnp4!think!sam
ark@alice.UucP (Andrew Koenig) (09/09/86)
Apparently I caught whatever was affecting Bjarne when he posted his original note about references. Sigh. I'll try again. Sam Kendall is right -- if you initialize a reference with something that isn't an lvalue then the reference refers to a temporary. Thus: char c; char &cr; /* illegal -- no initialization */ char &cr = c; /* legal */ char &cr = 'a'; /* equivalent to: char temp='a'; char &cr=temp; */ char &cr = &c; /* illegal -- &c is not a char */ Sam is also right in saying that initializers do not have to be explicitly provided for references declared as formal parameters. This is indeed because the initializers will appear whenever the function is called. Thus: void zap (int& x) { x = 0; } int z; zap (z); /* sets z to 0 */ However: double d; zap (d); /* illegal -- d is the wrong type */ zap ((int) d); /* sets a copy of the integer value of d to 0. Essentially no effect */
karl@haddock (09/09/86)
alice!bs (Bjarne Stroustrup) writes: >Karl W. Z. Heuer writes: >>BMS-AT!stuart writes: >>>[re the declaration of reference types "foo(char &c)"] >>>I don't like this. It violates the nice consistent way ... >> >>I am also somewhat uneasy about calling it "char &c". The consistent way to >>declare it would be "char *&c", since you have to write "&c" to get ahold of >>the "char *" object you are really using. > >The notation T& is the C++ notation for a reference to an object of type T. > char& c; declares c to be a reference to a char > char*& r; declares r to be a reference to a char* >& is a declarator operator exactly like * Understood. The point was that (in C) a declaration like "int *(*f[])();" asserts that "*(*f[])()" is an int (so one can work backwards to show that f must be an array of pointers to functions returning pointers to int). The use of "&" for the reference declarator operator breaks this heuristic; now "char &c" declares a reference to a "char", so "&c" is of type "char *". If the operator were spelled "*&" instead, then "char *&c" would denote a reference to a "char", "char **&r" would be a reference to a "char *", and "char &x" would be illegal. Since "**&r" really does give you an object of type "char", this notation might be easier to interpret. (I suspect that stuart was (incorrectly) applying this heuristic, and it led him to believe that "&c" was somehow an object of type "char".) Karl W. Z. Heuer (ima!haddock!karl; karl@haddock.isc.com) This isn't C (not even ANSI proposed), so let's move it to net.lang.c++, OK?