|
Hi ,
Your example doesn't prove anything. its as good as writing
int a = 10;
int b = 20;
int &ra = a;
ra = 20; // or ra = b;
Do you have any other point to prove that references != const pointer.
Gatik
|
|
|
|
|
Sorry if I was a bit unclear. My only point was that the compiler does not handle references like const pointers. The code shows that, unlike const pointers, references can be changed after initialization.
ra = b;
pa = &b;
|
|
|
|
|
Maybe classifying a reference to an alias or to a const pointer is rather philosophic.
But your comparison should be written like follows:
ra = b;
*pa = b;
at least this is what the original author claims.
Changing the pointer rather than the value it points to is like trying to change the reference rather than the value it's referencing.
so where is the problem??
|
|
|
|
|
Just to be clear, in C++, a "const pointer" is not the same as a "pointer to const". For the former, it's the pointer than cannot change, though its referent can. For the latter, the pointer can change, though its referent cannot. Seems to me that you are using the term "const pointer" as meaning "pointer to const". That's not true.
Short form:
int a;
const int* pi = &a; // this defines a pointer-to-const: you cannot change a through pi, but you can change pi
int* const cpi = a; // this defines a const pointer: you can change a through cpi, but you cannot change cpi
In your example, ra is a reference to the object a. ra cannot change (i.e., you cannot change ra to refer to a different object, once defined), though a can (as your example shows). That fits the definition of what we call a const pointer, not pointer-to-const.
See, e.g., 9.15 — Pointers and const | Learn C++[^]
|
|
|
|
|
int a;
int& b = a;
'a' is just a name for a variable, and 'b' is just a name for that same variable.
local/filescope names refer to variables and if you define a name via reference syntax it is just the same... Another name for that variable.
consider also
class foo {
int a;
int& b;
inline foo() : b(a) {}
};
In this case a compiler can make sizeof(foo) == sizeof(a) if it wants.
Even a normal variable can be implemented as a pointer, and in some cases for some compilers it is. So the reference is no different to a normal variable.
Also, when a function is inlined, a pass by reference can avoid using an address in the assembler, while pass by pointer cannot (unless the compiler can determine that its address is never taken, of course - in which case even pass by pointer doesn't use a pointer.
|
|
|
|
|
This is a great clarification on references in C++. The concept also loosely applies to any other language that uses references.
I hate to be the grammar police, but please don't flog the English language. Have someone proofread it for you if necessary. A well explained article like this deserves better, IMHO.
Thanks for the good read.
---
Shawn Poulson
spoulson@explodingcoder.com
|
|
|
|
|
there are similarities between reference and const pointers but they are not exactly the same.
Most compilers will work with pointers behind the scene to implement the references some of the time, but not all the time and perhaps not all compilers. See other replies for more details.
Add to this the fact that any decent C++ book should explain these things when talking about references and you get why Im not so excited about this article. But now the title is changed to "how compilers handle references" its a good article (it used to be "insights on references").
-- modified at 4:56 Thursday 20th April, 2006
|
|
|
|
|
Sorry, but this article is misleading and confusing. Right off the bat, you make a claim that "a reference is generally thought of an aliasing of the variable it refers to". Generally thought by who? And what exactly *is* this concept of 'aliasing'? And why isn't the definition of 'reference' as given by the Standard good enough?
On aliasing, the Standard only uses the term mainly (and normatively) to refer to namespace aliasing, and only in passing with respect to references, mainly in footnotes. The latter seems to be closer to what you are referring to, but it is nowhere defined in the Standard.
On references, the Standard says:
1) 'a reference can be thought of as a name of an object'
That's it, plain and simple. If that's what aliasing is, then what's your problem with the notion of aliasing? If aliasing is something else, then please feel free to actually define it before you rail against it.
2) 'it is unspecified whether or not a reference requires storage'
Again, very simply stated. In many cases, the compiler need not actually generate storage for an alias. Force the compiler into doing so, as you do in your somewhat contrived example (by the way, your class Test cannot be instantiated as is), then by golly, the compiler will generate storage.
The confusion comes into this article because seem to have this need of confusion implementation with definition. A reference is the name of another object, period; it is not a const pointer to an object. On the other hand, const pointer is a pretty reasonable implementation of reference, but that all takes place behind the scenes. Most programmers do not need to know how references work -- they just use them. References make coding easier because they are nicer syntactically, and because you are relieved of the need to check for null. Under the hood, of course, the compiler writer needs to make references work, but it's unlikely that there's any secret rule that says "hey, a reference is a const pointer". Just because a reference works like a const pointer in many cases doesn't mean that a reference is a const pointer. If you don't believe that, then ask yourself whether null-pointer checking is a good idea for const pointers?
Implementation is not interface, and to get very far in object-oriented design, you must be clear about the differences. Articles like this do not help.
|
|
|
|
|
Hi jefito,
I will try to remove your confusion(s).
Right off the bat, you make a claim that "a reference is generally thought of an aliasing of the variable it refers to". Generally thought by who?
6 out of 10 people will say references are alias. (My Experience and I hope developer community knows that.)
And what exactly *is* this concept of 'aliasing'?
I am not concerned about the concept of aliasing what my article suggests that references are not Alias.
And why isn't the definition of 'reference' as given by the Standard good enough?
Standards left it to compilers to implement it.
what's your problem with the notion of aliasing?
its not my problem. its developers problem who thought that using references a.k.a Alias will save the space on the stack. that's why I wrote References will take its own space in the memory.
Most programmers do not need to know how references work
They need to know. I strongly believe that because I am working on Real Time constrained memory environment and you must know what your compiler is going to do with your objects how many copies it will generate.
Just because a reference works like a const pointer in many cases doesn't mean that a reference is a const pointer. If you don't believe that, then ask yourself whether null-pointer checking is a good idea for const pointers?
I didn't understand this point very clearly but reference is a const pointer because there is no way you can have an alias in binary without occupying space.
Implementation is not interface, and to get very far in object-oriented design, you must be clear about the differences. Articles like this do not help.
With due respect to you I'd like to say that you must follow the etiquette of writing comments onto an open forum. You are writing comments in a way as you were a client asking for this article and my article didn't value for money you paid for this. CodeProject is a developer forum for worldwide developers and not to suite somebody's individual requirements.
Regards
Gatik
-- modified at 4:31 Thursday 16th March, 2006
|
|
|
|
|
""Just because a reference works like a const pointer in many cases doesn't mean that a reference is a const pointer. If you don't believe that, then ask yourself whether null-pointer checking is a good idea for const pointers?"
I didn't understand this point very clearly but reference is a const pointer because there is no way you can have an alias in binary without occupying space."
A reference variable is _not_ equivalent to a const pointer, period. The "alias"/reference is present only in compiler's intermediate representation, and then gets resolved into the appropriate register/memory cell equivalent to ones occupied by the variable the reference variable references. That's the reason you don't see it appear in the generatated binary.
The exceptions to this are when you globalize/make the reference variable static, or put it in a class similar to your "Test" class. Only then will you be able to track down the reference variable in the binary.
|
|
|
|
|
Gatik,
I would like to retract my previously posted disagreement with you. Please accept my apology, as I re-inspected the binaries, and found that you are right: references are indeed automatically dereferenced const pointers.
Reference variable do indeed possess memory cells, just like constant pointers. The only difference between them is that I see no way to access the actual memory address of the reference variable via the language itself, i.e. through any C/C++ semantic device such as &, *, &*, etc.
It's almost always good to learn something new !
-Ilya
|
|
|
|
|
Hi Ilya,
I agree, Healthy exchange of arguments always leads to good conclusion(s). Thanks ..
Regards
Gatik
|
|
|
|
|
So let me get this straight. You claim that '6 out of 10 people will say references are alias', yet you cannot be bothered to define what an alias is, when asked (leaving aside the dubiousness of your '6 out of 10' claim). You claim not to care what aliases are, yet you make a big deal in your article about aliases, and that references are not aliases. Strange. You have introduced a term that is not defined by the Standard, and then proceed to make all kinds of claims about developers beliefs. Please define what an alias is, and then we can talk about whether references are aliases.
To reiterate, the Standard says two things about references -- that they are the names of objects, and that they may or may not take up space (you have read the Standard, haven't you?). Beyond that, it doesn't say anyting about implementation, since reference is a semantic concept. You claim that they always take up space ("there is no way you can have an alias in binary without occupying space"), and that is incorrect. If you force them to take up space, as when including them in a class, then sure. But when you use them as with parameter passing, then there is no need for them to take up any memory space at all. They may, for example be passed to a function in a register, and never make it to a memory location, depending on the underlying hardware architecture, and the cleverness of the compiler.
I think that it's a good thing to try to understand what goes on 'under the hood', but again, not everyone actually needs that information. You do, with the environment that you use, but many Windows programmers, for example, who are library clients (and not library designers) do not.
Again, I repeat: a reference is not a const pointer, although it may be implemented by an underlying mechanism that behaves like one. Even if it were, it would be no guarantee that it exists in memory, much like the fact that there is no guarantee that any constant that you use actually exists in memory.
I also believe that you are incorrect about my etiquette here. I read your article thinking that that I would gain some insight into references. I did not. Instead, I find an article that I found extremely confusing and unhelpful, due to introduction of undefined concepts, over-generalization from one particular implementation to all computers, and claims that go directly against what the Standard says, and and claims against what my experience tells me. It doesn't matter whether I pay for this article or not -- open forum etiquette allows me to question your claims, and ask that you back them up. Spreading confusion about C++ concepts does not do service to the audience of worldwide developers.
Jeff
|
|
|
|
|
Hi jef,
I can buy your arguments only when if you can proof that compilers implements the references in any way, other than const pointers.
For your claim that in case of functions it might go into registers. This can be the case for simple variable also for efficiency reasons. Try to dig into assemble codes generated.
Finally, Standards may also not ask you how to implement virtual table in the memory but more or less it is done in a same way by most of the compilers (you can’t argue till you get proper functionality).
And finally aging I am sorry but I found your statement
Spreading confusion about C++ concepts does not do service to the audience of worldwide developers.
VERY outrageous. if you can prove that I am spreading confusion about C++ and audience can support that. I will withdraw this article very next day along with my written apology for this.
Regards
Gatik
|
|
|
|
|
Gatik G wrote: I can buy your arguments only when if you can proof that compilers implements the references in any way, other than const pointers.
For your claim that in case of functions it might go into registers. This can be the case for simple variable also for efficiency reasons. Try to dig into assemble codes generated.
I'm not quite sure that I understand -- are you asking me to provide you with examples of when references may not take up memory? Here's one that I found:
int array[10] = {0};
int& ri = array[3];
ri = 4;
It should be fairly straightforward for a compiler to optimize away the existence of the reference variable 'ri', and do the assignment directly to the appropriate array member. The compiler that I am using (Microsoft C/C++ 12/VS2003) generated the single 8086 assembly instruction for the assignment:
mov DWORD PTR _array$[esp+84], 4
No use of the variable 'ri', and it takes up no space. QED.
Further, a reference to a static object can generally be optimized away (or at least into machine code offsets). References used in functions that are inlined may be optimized into register-only values. Yes, I could post examples of these, but what's the point? I just showed one case where a reference doesn't take up any space.
Gatik G wrote: Finally, Standards may also not ask you how to implement virtual table in the memory but more or less it is done in a same way by most of the compilers (you can’t argue till you get proper functionality).
Whatever this means, it has nothing to do with references.
Gatik G wrote: if you can prove that I am spreading confusion about C++ and audience can support that. I will withdraw this article very next day along with my written apology for this.
It's my opinion that your article is confusing, because it lacks clarity with respect to C++ concepts, and makes incorrect assertions about references. Of course, since it's my opinion, it is not provable. But let me try to explain. From your article:
Gatik G wrote: I choose to write about the references in C++ because I feel most of the people are having misconception about the references and I have got this feeling because I took many C++ interviews and I seldom get correct answers about references in C++.
So what are the questions you've asked about references, and what are the answers that you get that are so incorrect and so misconceived?
By the way, one of the interview questions that I ask is: What's the difference between a pointer and a reference? If the candidate told me that they are identical, then I would have a big problem recommending that we hire them.
Gatik G wrote: What is meant by references in C++? A reference is generally thought of an aliasing of the variable it refers to. I hate the definition of references being and Alias of a variable in C++. In this article I will try to explain that there is nothing known as aliasing in C++.
Here, you begin by asking a question about the nature of references, then you introduce the notion of aliasing, that you somehow dislike. For the third time, what do you mean by aliasing, with respect to references? And then why do you claim that there is no such thing as aliasing in C++? As I read the Standard, there is no official notion of aliasing in C++, but I don't think that's what you mean. You could clarify by defining what you mean by aliasing. By leaving such an important concept (to the stated purpose of your article) undefined, you create confusion.
Gatik G wrote: Background
Both in C and in C++ there are only two ways by which a variable can be accessed, passes, or retrieved. The two ways are
1. Accessing/passing variable by value.
2. Accessing/Passing variable by address. In this case pointers will come into picture.
There is no 3rd way of Accessing/Passing variable. A reference variable is just another pointer variable which will take its own space in memory. The most important thing about the references is that its a type of pointer which gets automatically dereferenced (by compiler..). Hard to believe? Let see....
Why this strange excursion into accessing/passing variables? Why not just go to the Standard for the definition? It's very simple, and quite clear: "A reference can be thought of as the name of an object". Nowhere does it say that references are pointers; indeed, pointers are described in a separate section.
Gatik G wrote: References are nothing but constant pointer in C++. A Statement int &i = j; will be converted by compiler to int *const i = &j; i.e References are nothing but constant pointers. They need initialization because constants must be initialized and since the pointer is constant they can't point to anything else. Lets take the same example of references in C++ and this time we will use the syntax what compiler uses when it sees references.
References are not constant pointers. A common implementation of references is indeed by using pointers, but the standard does require that. Moreover, the compiler does not convert the statement int &i = j; into int *const i = &j;. This is nonsensical. Don't believe me? Try this code:
double d;<br />
double& rd = d;<br />
cout << "size of d = " << sizeof d << " size of rd = " << sizeof rd << endl;
If rd were converted by the compiler into a pointer, then what would you expect its size to be? Moreover, references cannot be null, while pointers can be null. You cannot have a reference to void, but you vertainly can have a pointer to void. You can't even have an array of references. A reference is not a pointer, period. There is no such rule as you cite; it is not like the rule "the subscript operator [] is interpreted in such a way that E1[E2] is identical to *((E1)+(E2))", which is in the Standard. You made your rule up.
Gatik G wrote: We can see this by checking the size of the class which is having only reference variables. The example below proofs that a C++ reference is not an Alias and takes its own space into the memory.
We have also seen by my examples above that a reference does not actually need to take up memory space. And by the way, this accords with what the Standard says. And again, what is an alias?
So, by my reckoning, your article introduces a concept, aliasing, that is never defined; claims that many people believe that references are aliases (if true, why is that a bad thing?), complains that that that belief is incorrect, and then goes on to make claims about references that are unsupported both by the Standard and by at least one actual implementation. And then forgets to prove that aliases don't exist in C++. It proves nothing about references except that they can take up memory space (if you've read the Standard's description, then that should come as no surprise), and I'm sorry, but in my opinion, that's confusing and unhelpful.
My suggestion: if you wish to describe why a reference might take up memory space, then you should begin by citing the definition from the Standard and that the Standard says that a reference might take up space. Contrast it against when a reference might not take up space (now that you know that they need not). Explain how a compiler might implement a reference as a pointer, sure, but don't claim that a reference is a pointer. And forget about the concept of aliasing, at least until you define it, and why it matters to a reference's size.
I'm sorry; you get points for trying to be helpful in this forum. But that's not enough if the material you provide isn't clear and correct.
regards,
Jeff
|
|
|
|
|
Hi Jeff,
jefito wrote: nt array[10] = {0}; // simple array
int& ri = array[3]; // reference to array member
ri = 4; // change array member through reference
It should be fairly straightforward for a compiler to optimize away the existence of the reference variable 'ri', and do the assignment directly to the appropriate array member. The compiler that I am using (Microsoft C/C++ 12/VS2003) generated the single 8086 assembly instruction for the assignment:
mov DWORD PTR _array$[esp+84], 4
No use of the variable 'ri', and it takes up no space. QED
Maybe with your compiler and on your system. On my system (I'm using PowerPC Linux natively running on a G4, compiling my code with gcc 4.1), the outcome is different. The code:
void testfunc1()
{
int array[10] = {0}; // simple array
int& ri = array[3]; // reference to array member
ri = 4; // change array member through reference
}
gets compiled into:
_Z9testfunc1v:
.LFB1489:
stwu 1,-80(1)
.LCFI6:
mflr 0
.LCFI7:
stw 31,76(1)
.LCFI8:
stw 0,84(1)
.LCFI9:
mr 31,1
.LCFI10:
addi 0,31,12
li 9,40
mr 3,0
li 4,0
mr 5,9
bl memset
addi 9,31,12
addi 0,9,12
stw 0,8(31)
lwz 9,8(31)
li 0,4
stw 0,0(9)
lwz 11,0(1)
lwz 0,4(11)
mtlr 0
lwz 31,-4(11)
mr 1,11
blr
The code:
void testfunc2()
{
int array[10] = {0}; // simple array
array[3] = 4;
}
gets compiled into:
_Z9testfunc2v:
.LFB1490:
stwu 1,-80(1)
.LCFI11:
mflr 0
.LCFI12:
stw 31,76(1)
.LCFI13:
stw 0,84(1)
.LCFI14:
mr 31,1
.LCFI15:
addi 0,31,8
li 9,40
mr 3,0
li 4,0
mr 5,9
bl memset
li 0,4
stw 0,20(31)
lwz 11,0(1)
lwz 0,4(11)
mtlr 0
lwz 31,-4(11)
mr 1,11
blr
The code:
void testfunc3()
{
int array[10] = {0}; // simple array
int *const rp = &array[3]; // pointer to array member
*rp = 4; // change array member through const pointer
}
gets compiled into:
_Z9testfunc3v:
.LFB1491:
stwu 1,-80(1)
.LCFI16:
mflr 0
.LCFI17:
stw 31,76(1)
.LCFI18:
stw 0,84(1)
.LCFI19:
mr 31,1
.LCFI20:
addi 0,31,12
li 9,40
mr 3,0
li 4,0
mr 5,9
bl memset
addi 9,31,12
addi 0,9,12
stw 0,8(31)
lwz 9,8(31)
li 0,4
stw 0,0(9)
lwz 11,0(1)
lwz 0,4(11)
mtlr 0
lwz 31,-4(11)
mr 1,11
blr
Now, Jeff, notice that the codes generated for testfunc1 and testfunc3 are the same. testfunc2, on the other hand, gets a compiled into a different set of instructions. QED (FOR GCC on PowerPC).
By the way, are you sure that your wonderful Microsoft compiler didn't simply optimize the reference variable away? Try my version of your code that uses a const pointer instead of a reference (in testfunc3) and see what code the compiler will produce. If it produces the same assembly code as before, please try to turn-off the optimizer and then see what happens.
I hope that Gatik will forgive me, if I interpret him that by saying that "many people think of a reference variable as an alias" he meant to say this:
Many people think that a declared&defined reference variable is interpreted by the compiler to be just another name for the original variable.
And that's as simple as that. Gatik then proceeded to say that the above notion is generally not true. What's your problem with that?
Gatik *does not say* that references are the same as const pointers. What he says is that they are the automatically dereferenced versions thereof. That's why in your code snippet:
jefito wrote: double d;
double& rd = d;
cout << "size of d = " << sizeof d << " size of rd = " << sizeof rd << endl;
You get "8."
Another interesting example is taking the address of "rd." You will get the same number as that for "d."
That's why I view reference variable as const pointers with a twist. I don't know how the Microsoft compiler implements them, but in my case: if a reference variable doesn't occupy any space, that means that, if a corresponding const pointer is defined instead, it, too, will be optimized away.
I hope I didn't introduce any more confusion than is already there!! In fact, I also hope that I clarified some.
I do, however, agree with you on this: maybe the author should indeed be more precise, elaborate, and rigorous when explaining the relation between references and const pointers. It is a site that often gets visited by knowledgeable folks, after all.
Regards,
Ilya
|
|
|
|
|
Ilya Lipovsky wrote: Another interesting example is taking the address of "rd." You will get the same number as that for "d."
Obviously, one example is all it takes to disprove the assertion that a reference always takes up memory.
Ilya Lipovsky wrote: By the way, are you sure that your wonderful Microsoft compiler didn't simply optimize the reference variable away?
Well, in a sense it did, because 'ri' is just another name for the object stored at array[3]. It didn't need to actually reserve storage for the variable. And that's the point; it's what the Standard says. Perhaps it's not that Microsoft's compiler is so wonderful, but that your compiler is less-than-wonderful that you don't see the same effect.
Ilya Lipovsky wrote: I hope that Gatik will forgive me, if I interpret him that by saying that "many people think of a reference variable as an alias" he meant to say this:
Many people think that a declared&defined reference variable is interpreted by the compiler to be just another name for the original variable.
And that's as simple as that. Gatik then proceeded to say that the above notion is generally not true. What's your problem with that?
My problem with that is that that definition of reference is exactly true: a reference is just a name for an object. Please see the Standard, or Stroustrup, or any number of reputable C++ authors if you don't believe me. If that's what Gatik means by aliasing (and I'm not sure that it is), then his assertion that a reference is not an alias is incorrect.
Ilya Lipovsky wrote: Another interesting example is taking the address of "rd." You will get the same number as that for "d."
Guess what. You can't take the address of a reference. That is, the following is illegal:
double d;<br />
double& rd = d;<br />
double&* prd = &rd;
Ilya Lipovsky wrote: That's why I view reference variable as const pointers with a twist. I don't know how the Microsoft compiler implements them, but in my case: if a reference variable doesn't occupy any space, that means that, if a corresponding const pointer is defined instead, it, too, will be optimized away.
You may view them any way you want to, but to me it's confusing to introduce the concept pointers into the mix: a pointer is a name for an object. Period. In some situations, it requires no storage -- it's just a convenience to the programmer. It's nice, because you don't need to test it for null when you receive one.
I think what is going on here is that Gatik is working at too many levels at once. At the level of the programmer, a reference is certainly not a pointer, and it's not particularly helpful to think of them in any such light. At a different level, the level of the compiler implementor (and possibly the developer who is counting cycles/bytes), you need to know how they're implemented. But mixing levels inappropriately is confusing. And insisting that references always take up memory is just incorrect.
regards,
Jeff
|
|
|
|
|
Don't forget: it's not const pointers, but automatically dereferenced const pointers.
But I get your point, Jeff. On the level of C++ semantics you _may_ be right. I can't check you on that one, since I don't have the standard on hand. I still have my doubt, though, since what you quoted from there says: "A reference can be thought of as the name of an object". What is the meaning of "can?" The same as "should?"
On the level of implementation, things do get tricky. In my case Gatik is absolutely right! In your case... I didn't see you following up on my request to you to check what testfunc3 gets compiled into without optimizations being turned on.
Also, don't be too quick to criticize gcc: if I turn the -O3 optimization on, my modified testfunc1, testfunc2, and testfunc3 all produce the same very short code. (I modified them to force the optimizer to not throw them away, since they previously returned void and had no side effects).
int testfunc1() __attribute__ ((noinline));<br />
int testfunc2() __attribute__ ((noinline));<br />
int testfunc3() __attribute__ ((noinline));<br />
<br />
int testfunc1()<br />
{<br />
int array[10] = {0};
int& ri = array[3];
ri = 4;
return ri;<br />
}<br />
<br />
int testfunc2()<br />
{<br />
int array[10] = {0};
array[3] = 4;<br />
return array[3];<br />
}<br />
<br />
int testfunc3()<br />
{<br />
int array[10] = {0};
int *const rp = &array[3];
*rp = 4;
return *rp;<br />
}<br />
<br />
int main()<br />
{<br />
std::cout <<testfunc1()<< std::endl;<br />
std::cout <<testfunc2()<< std::endl;<br />
std::cout <<testfunc3()<< std::endl;<br />
}<br />
the C++ code above will produce the following assembly definitions for the testfuncs:
_Z9testfunc1v:<br />
.LFB1525:<br />
stwu 1,-16(1)<br />
.LCFI2:<br />
li 3,4<br />
addi 1,1,16<br />
blr<br />
.LFE1525:<br />
.size _Z9testfunc1v, .-_Z9testfunc1v<br />
<br />
<br />
.align 2<br />
.globl _Z9testfunc2v<br />
.type _Z9testfunc2v, @function<br />
_Z9testfunc2v:<br />
.LFB1526:<br />
stwu 1,-16(1)<br />
.LCFI3:<br />
li 3,4<br />
addi 1,1,16<br />
blr<br />
.LFE1526:<br />
.size _Z9testfunc2v, .-_Z9testfunc2v<br />
<br />
<br />
.align 2<br />
.globl _Z9testfunc3v<br />
.type _Z9testfunc3v, @function<br />
_Z9testfunc3v:<br />
.LFB1527:<br />
stwu 1,-16(1)<br />
.LCFI4:<br />
li 3,4<br />
addi 1,1,16<br />
blr<br />
.LFE1527:<br />
.size _Z9testfunc3v, .-_Z9testfunc3v<br />
I tend to work with assembly so that's why I put my 10 cents into this whole discussion.
Regards,
Ilya
|
|
|
|
|
It doesn't matter if pointers might be optimized away. The reference still doesn't take any memory, independent from what happens with pointers.
The article claims that "A Reference takes its own space in memory", wich is proofen to be wrong.
Further the article says: "The example below proofs that a C++ reference is not an Alias and takes its own space into the memory." followed by an example. But an example can never proof that something is right. Otherwise I could "proof" that all odd numbers are prime numbers. 3 is a prime numbber; QED.
|
|
|
|
|
Hi Matthias,
I'd like to ask one question to clarify your confusion.
Is it possible to write an assembly code in which you can specify one variable which will not take any space in memory/registers ? if yes, the concept mentioned above is wrong and I aplogize for that.
No body in the discussions till now being able to proof that a reference will not take its own space in the memory. some people say its wrong but I dont understand why . I can clarify if more confusion's are there.
Regards
Gatik
|
|
|
|
|
OK, back into the fray.
Gatik G wrote: Is it possible to write an assembly code in which you can specify one variable which will not take any space in memory/registers ? if yes, the concept mentioned above is wrong and I aplogize for that.
Where in your article do you talk about registers? They are not generally considered to be part of memory space (though some architectures do map registers into memory space). Here is what you say:
Gatik G wrote: A reference variable is just another pointer variable which will take its own space in memory.
This seems to imply that a reference variable has its own location in the memory space, separate from other variables. Since registers get re-used, you cannot include registers in your criterion. In general, most things go through registers at one time or another.
Gatik G wrote: No body in the discussions till now being able to proof that a reference will not take its own space in the memory.
I gave you an example in a prior post, with assembly code output to prove it. Would you like another?
void func( int* array, int val )<br />
{<br />
array[4] = val;
int& ri = array[3];
ri = val;
}<br />
Here is the generated assembly:
PUBLIC ?func@@YAXPAHH@Z ; func<br />
_TEXT SEGMENT<br />
_array$ = 8<br />
_val$ = 12<br />
?func@@YAXPAHH@Z PROC NEAR ; func<br />
; File ref2.cpp<br />
; Line 7<br />
mov ecx, DWORD PTR _array$[esp-4]<br />
mov eax, DWORD PTR _val$[esp-4]<br />
mov DWORD PTR [ecx+16], eax<br />
; Line 9<br />
mov DWORD PTR [ecx+12], eax<br />
; Line 10<br />
ret 0<br />
?func@@YAXPAHH@Z ENDP ; func<br />
_TEXT ENDS<br />
<br />
Do you need to have this explained to you, or can you figure out that nowhere does the reference 'ri' exist in a separate location in memory: the code loads the address of the array into the ecx register, and then accesses the appropriate array entry via offset from the register contents. There is no place where the variable 'ri' is stored; not in memory, not in the register.
Gatik G wrote: some people say its wrong but I dont understand why.
Just because you don't understand why it's wrong doesn't make it correct.
Again, let's go back to your article. You say in your Introduction:
Gatik G wrote: What is meant by references in C++? A reference is generally thought of an aliasing of the variable it refers to. I hate the definition of references being and Alias of a variable in C++. In this article I will try to explain that there is nothing known as aliasing in C++.
You go on and on about aliasing, but you never explain why you don't believe in it, or don't like them. When asked, you don't provide a definition. What is aliasing, in your mind? Why is it so hateful to you?
Gatik G wrote: A reference variable is just another pointer variable which will take its own space in memory.
This is contrary to what the Standard says, and contrary to examples given to you.
You might also check out the book "C++ Common Knowledge", by Stephen C. Dewhurst. Chapter 5 is called "References Are Aliases, Not Pointers".
Gatik G wrote: The most important thing about the references is that its a type of pointer which gets automatically dereferenced (by compiler..).
The closest thing I could find to this point of view is Stroustrup's "The C++ Programming Language" (2nd ed.), where he says "The obvious implementation of a reference is as a (constant) pointer that is dereferenced each time it is used". However there is no guarantee that there will actually be a place in memory space that holds that value, which is what the Standard says. Sometimes there, is, and as shown above, sometimes there isn't.
I still find your article to be confusing, and just plain incorrect with respect to what the Standard says and to what code examples show. You can't seem to be bothered to address either criticism. Why not? You don't seem to want to actually define your concept of aliasing, which is so important to you since the point of the article is to prove that references are not aliases.
I don't know what else to tell you -- you are to be commended for trying to contribute to the community, but this article remains incorrect and unhelpful,
regards,
Jeff
|
|
|
|
|
Hi Jeff,
I request you to just look at the added section of this article. Your comments were very useful and I would like to have some comments from you regarding the new section.
Regards
Gatik
|
|
|
|
|
In my opinion Jeff is right! Standard says it's just a name for an object an the compiler builders are free to implement them with their needs to the underlying architecture considering that the reference is only a name for another object. Pointing to Gatik ... in real world we would name it an 'alias' but this is, as Jett proved is not the right terminology of programming. Wether there is optimization or not!
The standard only tells you how to implement the pattern an nothing about the generated assembly.
Thats my opinion. Am I wrong?
Live is to short to be angered about lost chances!
|
|
|
|
|
I dont see the problem, a reference is just another name for a variable (aka alias),
this means that the code:
<br />
int j=5;<br />
int &rj = j;
rj = 6;
can be replaced by the compiler to:
<br />
int j=5;<br />
j=6;<br />
however, sometimes the logic needs to know which variable is referenced in *runtime* which then simple symbol-table compile time logic cant handle, and you must have a runtime solution, the most simple and logical is using a const pointer to hold the address of the aliased variable. The most obvious example is parameter passing to a function.
however (again) some wierd architectures and wierd compilers can choose a different approach, they are free to do so.
Any decent C++ book will explain this at the chapter about references and I dont see the need for the article (or how the article helps explain things).
as for the virtual table at the end of the article, it doesnt proof a thing except that the author is confused about what aliasing is, as this example makes sense for aliasing as well.
As a1 is just another name for c1 so the code changes to c1.print(). The type of a1 isnt much relevant. True it makes sense to think of it as const pointer but it doesnt *have* to be a const pointer, it could be compile time symbol table replacment.
Iftah.
-- modified at 8:25 Wednesday 19th April, 2006
|
|
|
|
|
Ken,
Jeff may be right in the sense that Mr. Stroustroup himself would agree, and even drink tea/coffee and philosophize with him about how not to hire people who disagree. The problem, however, is that whatever the standard says is not the way some very popular compilers implement the concept of references.
There is a difference between "automatically dereferenced const pointer" and "alias."
In the first case the compiler is obligated to treat all reference variable declarations as const pointer declarations, and automatically dereference all further instances thereof, before proceeding with further compilation and potential optimizations. It should generate the same code that would be generated, if the user were to replace all uses of reference variables by dereferenced const pointer equivalents (with their initializations being the exception: not dereferenced, but having "=" replaced with "= &").
In the latter case, however, the compiler has to preprocess all instances of reference variables and resolve them into the name of the variable they reference. Basically, the same as #define'ing, only performed at compile-time, instead of preprocess-time. The code generated in this case is essentially the same as running the C preprocessor appropriately.
Gatik said that the first situation holds true, not the second one.
After initially disagreeing with him (I thought it was the second case), I performed some tests with gcc on PowerPC, and had to retract.
Again, I don't know whether Visual C++ implements reference variables with automatically dereferenced const pointers or aliases, but in gcc world the first holds true.
I still look forward to compilation results on Visual C++. Jeff indeed provided some, but I want to make sure that optimizations were turned off. Why it matters? Even with Gatik being right, the compiler *may* be smart enough to "realize" during a certain stage of compilation (like the SSA stage of gcc) that all reference variable names can be optimized away and replaced by the name of the original variable.
In a sense, it's like the alias concept, only implemented in the middle of compilation, not on the front end / parsing stage of the compiler.
-Ilya
|
|
|
|
|