|
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
|
|
|
|
|
Ilya Lipovsky wrote: The problem, however, is that whatever the standard says is not the way some very popular compilers implement the concept of references.
Really? That's a bold claim. Which compilers? How do they differ?
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.
Really? Where is that statement mandated? What section of the Standard?
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 "= &").
And again, where is this claim from?
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.
What are your sources for this information?
Gatik said that the first situation holds true, not the second one.
If Gatik indeed thinks that an alias is another name for an object (not a variable, as you seem to think), a term that he either won't or can't define for his readers, Gatik is incorrect in his claim, something that I showed with a concrete example. If by 'alias' he means something else, his obligation is to define it.
After initially disagreeing with him (I thought it was the second case), I performed some tests with gcc on PowerPC, and had to retract.
Neither you nor Gatik seem to understand the nature of proof. It's as if Gatik were claiming that all humans are left-handed. All of the humans that he knows are left-handed, and you found a human who is left-handed, there for you think that that's a proof. Even though I can point to a human who is not left-handed, you and he continue claiming that you have proved the assertion. You are both incorrect.
Ilya Lipovsky wrote: 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.
You don't seem to understand the distinction between what the Standard requires and what it allows. Nearly everyone agrees references behave in at least some respects like a const pointer, but there is no guarantee that it is identical, nor that it be implemented using pointers. I am guessing that that holds true with gcc; I've already shown that is does with VC++. All you have shown is that gcc implements them like that in some cases, but that does not in any way constitute a proof. Have you examined the specifications and source code for gcc to validate your claim? I hope that I don't have to rustle up a copy of gcc to find a counterexample in there as well.
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.
You seem confused on the topic of optimization. Optimization is in the realm of implementation -- there's no requirement that a compiler provide certain optimizations, nor is there a requirement that a compiler not provide certain optimizations by default. The compiler is largely free to do as it sees fit, so long as the meaning of the program is preserved. It can implement variables in registers, remove unused variables, inline functions, move computations around, and so on. Whether it does things by default, or as a result of compiler settings is irrelevant -- if the meaning of the program is preserved, it's all fair game --- it's implementation-dependent. Whether I had VC++ optimisations turned on or off does not matter -- the program was compiled into correct code, without the use of any memory space for the reference.
In the end, all of this comes down to the simple statement that "a reference is another name for an object". It's a simple notion, and is supported by the Standard and other reference literature, as well as existing compilers, even gcc. There's no requirement that a reference take up memory space, as Gatik claims. This is false, as examples have shown.
regards,
Jeff
|
|
|
|
|
Before accusing me of being "confused," **please** do read the previous posts I wrote. In those posts I gave examples of gcc generating binaries wherein reference variables and original variables *do occupy* different memory locations.
Yes, I know that optimization is a realm of implementation. Moreover, this is the realm I work in and get paid for contributing to, Sir.
My participation in the discussion is not to teach you or anyone else about the Standard, my point is to provide anyone interested with my personal annotation to the Standard. I presume that the same purpose Gatik had as well but am not going to vouch for it. You are free to read and forget it.
Also, Sir, you mistake my desire to comment with a desire to argue. I do not desire to "prove" anything in general. I only wish to illustrate that compilers have a mind of their own, while still providing an end behavior consistent with the Standard.
I do not posit any things I did not personally verify by experimentation. The terms "aliases" and "automatically dereferenced const pointers" served merely as a personal explanatory glue to explain how implementations *may* proceed compiling references. The end results *do* (verified in practice!) vary in binary, but compiled program's behaviour dictated by the standard *does not.*
The further theorizing I was engaged in *I* consider to be interesting, because it explains to me why I was getting the results I was getting with gcc, and because I deal with assembly and gcc/g++ rather often. Again, you are free to read and forget it, as it is targeted for people with some practical/similar experience. It is targeted for people who want to ruminate about the state of things in real world, not just what standards say.
End of discussion.
|
|
|
|
|
Ilya Lipovsky wrote: Before accusing me of being "confused," **please** do read the previous posts I wrote. In those posts I gave examples of gcc generating binaries wherein reference variables and original variables *do occupy* different memory locations.
Please feel free to note that what I actually said was that you "seem confused", and that was with respect to the role of optimization in compilers. It's an opinion, not an accusation, and subject to change, should you want to try to change my mind. Maybe I've misinterpreted what you said, but in prior posts, you insisted that I submit unoptimized generated code here. To what end, I can't understand -- the code would only tend to validate an entirely unsurprising conclusion: that references can be implemented as pointers. This is less strong than what the original article claims (as nearly as I can make out, because the article seems confused to me also), namely that references must be implemented as pointers. Your pursuit of the less surprising and hence, less interesting result led me to believe that you were confused on the role of optimization.
As for the rest, all noble words, indeed, but rather off the main point of the article, I think. In your prior post, you made assertions that I found questionable, and so I questioned you. For example, right at the start, you said:
The problem, however, is that whatever the standard says is not the way some very popular compilers implement the concept of references.
I found this very surprising, and asked you to clarify by naming the particular compilers, and how they differ from what the standard says about references. And what is this "concept of references" you mention? Can you actually back up what you assert?
Next, you made some claims about how a compiler must operate [snipped for brevity's sake]:
...the compiler is obligated to treat all reference variable declarations as const pointer declarations...
Again, I was surprised, and asked you to support your position. If "the compiler is obligated", then it is obligated to some set of rules (the Standard?). Who or what is it obligated to?
And so forth. You may theorize, ruminate, personally annotate, or whatever it is you think you're here for, but in the end, if you make concrete claims about the behavior of compilers vs. the Standard, you ought to be prepared to back them up. This is similar to my objections to Gatik's article wherein he claims that references are not aliases, and then can't or won't define what he means by the term 'alias'. The kindest interpretation that I can come up with for that type of behavior is "confusion".
regards,
Jeff
|
|
|
|
|
I'm explaining what I mean by the word "obligated:"
"Obligated" was a part of my definition of how references *may* be implemented as automatically dereferenced const pointers.
I also use the word "obligated" as a part of another definition of mine: how references *may* be implemented as "aliases," i.e. I essentially defined what I mean by the term "alias."
These are my definitions / convenience terms. These may or may not reflect the actual way how references are implemented in practice. Nevertheless, since I've done related work and involved experiments (some of which I already provided in earlier posts), I feel that my suggestions deserve to be on this forum.
-Ilya
|
|
|
|
|
Ilya Lipovsky wrote: I'm explaining what I mean by the word "obligated:"
"Obligated" was a part of my definition of how references *may* be implemented as automatically dereferenced const pointers.
Thank you for the clarification. There's a big difference in meaning between "obligated to be" and "may be".
I also use the word "obligated" as a part of another definition of mine: how references *may* be implemented as "aliases," i.e. I essentially defined what I mean by the term "alias."
I can't see how you could implement references using aliases. Seems strange to me. Do aliases exist in machine code? Pointers (memory addresses) do. Aliases, probably not, because an alias is a name, and machine code is generally stripped of names. Aliasing is a higher level concept, more appropriate at the C++ semantic level.
This is why I think that the topic in the original article is turned upside-down. The simplest approach, for a beginning programmer, and as a base definition, is this: A reference is an alias. Or more precisely, a reference is a name or alias for another object. This removes this useless and confusing dependence on the concept of pointers which Gatik and you (I think) evidently want to force on the concept of references.
Oh, so now you want/need to know how they're implemented? Well, OK, one way is via pointers, sure, and there are some usages that virtually require that. For one, if you want to store a reference inside a class, the best solution is likely to be a pointer. Another is when you are passing a reference to a function. But there are some instances when no pointer is required; the compiler, knowing that a reference applies in a local scope to some local object may substitute the original's address as needed, and no independent storage for the reference need be allocated.
I believe that many programmers don't care, or need to know how references are implemented; a name for another object will do fine.
The above definition of reference is in line with my own check of a real life compiler's behavior, and also with my reading of the Standard and other materials, all of which I've detailed in previous postings.
These are my definitions / convenience terms. These may or may not reflect the actual way how references are implemented in practice. Nevertheless, since I've done related work and involved experiments (some of which I already provided in earlier posts), I feel that my suggestions deserve to be on this forum.
I doubt that anyone is questioning your right to post here; I certainly am not. But posting in a public forum leaves your posts open to questioning, does it not?
I am still waiting for the names of the popular compilers that implement references contrary to the standard.
Jeff
-- modified at 14:01 Tuesday 2nd May, 2006
|
|
|
|
|
Wait a sec! There is probably indeed a context miscommunication here. I assumed that you were denying the very possibility that the generated binaries contain separate memory locations for reference variables and the original variables.
In any case, I was referring to my findings on GCC (how many times do I have to repeat?) that suggest that the binaries generated from C++ code with references are exactly the same as the ones generated from C++ with always dereferenced const pointers. Remark: I did not experiment with references to functions.
Again, make an effort and check these posts to see for yourself what I was talking about. And please don't take things out of context (like with the verb "obligated").
If you are not denying the possibility that reference variables reside in their own separate memory locations, then I say this: gcc generates code consistent with the Standard.
Regarding my examples on gcc: I realize that I did not (nor could not, unless I were an active gcc contributor) provide a general proof of required rigor - merely a hypothesis supported with examples for practical guys like myself to take a note of.
I do agree with you on one thing: it's important for anyone to draw a line between specification and implementation. Believe it or not, I saw that point from the moment you entered the forum, and I fully understand and appreciate what you try to do. You need, however, to express that point in a more "gradual" manner (as ridiculous as it may sound). Otherwise, hormons start to pump and people get defensive. That is just input/output from another human, as there is plenty of other things to get heat up about in this world. Actually, what you said in this post should have been said in the very beginning!
And speaking of *implementation*, actually, I am still waiting for you to verify how VC++ compiles code with references vs. dereferenced const pointers with optimizations turned off (for my own knowledge).
-Ilya
|
|
|
|
|
Before you complain any more about me not reading your posts (I have), perhaps you should go back and reaquaint yourself with my very first post on this topic, the first on in the thread, in which I discuss the possibility and even the reasonableness of implementing references with pointers, in some situations. I do not deny this, and never have -- I can't imagine why you would think from my postings that I could think this. Unless perhaps you never read what I wrote very carefully.
Because I have had this understanding all along, I have considered a lot of your and Gatik's examples irrelevant to the issues at hand (more left-handers, to continue my analogy of a couple of posts prior). You can stop repeating yourself -- whether a particular compiler actually implements references exactly the same as constant pointer doesn't matter in the least to me, and provides little, if any, help to the overall confusion of the article. It's why I can't be bothered to compile your code snippets with VC++ -- the result would really be irrelevant to my objects to the article.
Regarding context and the verb "obligate" -- I read what you wrote in the context you provided. How was I to know that when you wrote "obligated" you meant "permitted" or "might"?
Regarding gcc: it may or may not behave in the way that you describe. It doesn't matter a whit to me, so long as it meets the Standard with respect to references. I never claimed that it didn't, or made any claims about it's implementation. If you though that I did think any such thing, then please point out what I wrote that implied that.
Ultimately, my main point is, and has been, that the article's insistence that references are not aliases is incorrect, as is its implication that references must always take up memory space. The former is contradicted by the Standard and by reliable sources; the latter also by the Standard and by my own experiments. Will Gatik ever return to explain his use of the term 'alias', and his detestation of the very idea that a reference is an alias? Who knows?
But in the above light, I cannot help but wonder why it is that you so thoroughly agree with his conclusions. For example, you 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?
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:
My problem with that is that your restatement of Gatik's position (whether or not it accurately reflects his position), or at least what the statement's referenced "many people" think is actually always true at the level of C++, as supported by the Standard. How is a reference not an alias? At implementation level, a reference couldn't be an alias, because aliases don't exist in any machine code that I'm aware of. But that says nothing of interest, much the same as if he claimed that a reference is not a dog -- dog's don't exist in any machine code that I am aware of either. Quelle suprise.
Look, here's what he actually says in his 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++.
Is there anything there that paragraph that talks about anything at implementation level? No, it's all about the concept of references in C++.
Further, he says:
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.
...
The most important thing about the references is that its a type of pointer which gets automatically dereferenced (by compiler..).
So indeed he does actually say that references are nothing but const pointers (is an automatically dereferenced pointer somehow not a pointer? Are you confusing that with the result of a dereferenced pointer?). He makes assertions about the compiler that are unsupported (maybe we should change "will" to "might". Hmmm, sound familiar?) He makes claims about the syntax that the compiler uses when it sees references. Again, unsupported. More reading out of context? I don't think so. And he never, ever, allows for the possibility that a reference might not take up memory space.
I'm sorry, but his introduction is so riddled with confusion, that it's hardly useful to proceed with the remainder of his article. So why do you agree with him so happily?
And by the way, just what compilers are out of sync with the Standard with respect to references, and how do they differ? You said that they exist -- so what are they?
Jeff
|
|
|
|
|
Regarding what I said about existence of compilers that implement references not consistently with the Standard: I retracted that assertion (see the bold type in my previous post).
I did it, because I saw that you did not use what the Standard was saying as a denial of the possibility of references being resolved into ADCPs (automatically dereferenced const pointers). Since I don't have the Standard on hand, and I am not anal about it, I wanted to see whether you connect your understanding of the Standard to insisting (as formerly&mistakenly I thought that you did) that references cannot resolve into ADCPs. I took the Standard as "hostage," if you may.
Hope that makes sense .
In my previous post I completely recognized that you were not implying that references can't resolve into ADCPs, so restated myself.
I was so "happily" agreeing with Gatik, because even before you joined the discussion I made another mistake. I originally thought that references do not resolve into ADCPs, but instead are "aliases," as was defined by me.
Obviously, both you and Gatik would strongly disagree with that. I realized that I was wrong after performing my experiments with gcc and admitted it. Probably, from then on I proceeded by inertia, thus so "happily" disagreeing with you. I took his article as a comment on implementation, not as a comment of how things should be. Thus, I was wrong yet another time.
In total, I was wrong thrice:
1) I thought that references are strictly "aliases" (compile-time ones, as defined by me). Corrected myself before Gatik.
2) Thought that Gatik was enlightening the crowd about implementation. Not true, in light of the pasted text. Apparently he's talking about specification.
3) Mistook your fanaticism in defending the Constitution... sorry, the Standard, as a denial of the obvious. Corrected myself before you (right?).
Hopefully, those things answer everything completely.
-Ilya
P.S. Sorry for the joking tone, but the hour is late, and I just can't things too seriously right now.
|
|
|
|
|
Well, that's a very gracious post, Ilya. What can I do but marvel, and back off? I think that ultimately we may have been in violent agreement on some points, and I'm sorry for any misunderstanding that may have been caused by me.
No need to apologize for your joking tone -- the tone was probably getting too heavy anyways. I certainly felt it in some of my own posts. I think that we're clear now -- if only we could get Gatik to come around and clarify his article.
regards,
Jeff
|
|
|
|
|
Let me also answer:
>I can't see how you could implement references using aliases. Seems strange to me. Do aliases exist in machine code? Pointers (memory addresses) do. Aliases, probably not, because an alias is a name, and machine code is generally stripped of names. Aliasing is a higher level concept, more appropriate at the C++ semantic level.
Exactly! By "alias" I meant that the compiler may convert all uses of reference variables into the names of the variables they refer to (if such use is permitted) at parse / early compile time. That's why I said that it may be like the #define statement, only at early compile time. The produced binary will not contain any mention of the reference variable, which may explain why you did not see it in your examples.
I also said that gcc appears to be interesting in this respect: it most probably resolves references into dereferenced const pointers and then proceeds into further compilation.
If no optimizations are enabled, one can detect the presence of the reference variable. In fact, the produced code looks the same as if dereferenced const pointers were used instead.
However, if optimizations are anabled, gcc (v4.0+) performs alias analysis and attempts to get rid of references (by resolving them into the actual variables when possible). Since references were resolved into const pointers, the same thing is being done to const pointers as well.
That's why I said that it's like the "alias" concept (as was defined by me), only implemented during the optimization stage, not at the early stage of compilation.
|
|
|
|
|
I'm sorry, but adding irrelevant information to an incorrect and confusing article doesn't make it any less incorrect and confusing. Until you address some of the specific problems in your Introduction, which I have mentioned several times already, this article will remain, for me, completely useless.
Well, useless except for one thing: since I participate in technical interviews where I work, I now have a new interview question to explore: "what is the difference between a referenc and a pointer?" A candidate who claims that a reference is a constant pointer or that a reference always takes up memory space will have some serious follow-up to face.
regards,
Jeff
|
|
|
|
|
Hi jef,
Well I was out of action for a while but again I dont agree with your point. The problem is that you are mixing compiler optimization with reference implementation unnecessary. for example
when you call a function the you might get few parameters inside the registers instead of being into the stack. Then if you argue that when I haven't mentioned __fastcall why some parameters goes to registers.
furthermore a compiler can optimize only things it can foresee, and for the variable about which it cant foresee where the variables are going to be used.
I can agree with one point that I should rename this article as "Compilers handling of reference variables when it cant foresee its usage".
For my perspective if somebody in my interview says that the references are alias, they have serious consequences to face actually.
The thing is you have shown all the examples which is having compiler optimization. Well I want to come into conclusion so I just wanted one thing from you or Ilya that keeping in mind what the standard says, if you have to implement references how you would have written compiler to implement that.
I would like to make a point over here that Concept of having an Alias which will not take any space, if it would have been the case, there is no reason why "C" language skips that. everybody want to save space using aliases, isn't it ?
Any comments
Regards
Gatik
|
|
|
|
|
Well, once again, you have either forgotten to, or chose not to define "alias", which you so strongly object to. In your article, you say:
What is meant by references in C++? A reference is generally thought of an aliasing of the variable it refers to.
Yet you never define what aliasing is. Do you define it as "another name for an object", which would make it identical to what references are defined to be, in the Standard and by other knowledgeable authors? Or is it something else? You've been asked to provide your definition several times -- until you do so, it's very difficult to understand what your difficulty with the concept of references being aliases actually is.
I hate the definition of references being and Alias of a variable in C++.
Whether you hate it or not, references are aliases, if aliases are another name for an object.
In this article I will try to explain that there is nothing known as aliasing in C++.
You prove no such thing -- you merely show examples where references are implemented as pointers. I have shown you examples where references can be seen to be implemented as aliases, i.e., where a reference is used in C++ source, no separate pointer representing that reference appears in the generated machine code. This disproves your theory, and so does the fact that your theory contradicts against what the Standard says.
To continue with your latest reply:
Gatik G wrote: Well I was out of action for a while but again I dont agree with your point. The problem is that you are mixing compiler optimization with reference implementation unnecessary. for example
There is no problem here; compilers are obligated to honor the semantics of C++ constructs when compiling code. Even if optimization is on, that optimization doesn't allow the compiler to change the semantics of C++ programs. The implementation of references, regardless of optimization, in C++ does not require pointers to be used, nor does it require that space be allocated to implement a reference.
A similar example: in the expression i / 2, where i is an int, the compiler is free to do an actual division, or do a right shift (i >> 1), if it doesn't change the meaning of the program? Is it optimization? Perhaps. Is that somehow invalid? No, because the program does the same thing either way.
Gatik G wrote: For my perspective if somebody in my interview says that the references are alias, they have serious consequences to face actually.
Why, because the interviewee is actually correct, and you are not? They can easily point to the Standard and other reputable authors to support that references are exactly aliases. You cannot. It's a different question than "how might you implement references?"
Gatik G wrote: The thing is you have shown all the examples which is having compiler optimization. Well I want to come into conclusion so I just wanted one thing from you or Ilya that keeping in mind what the standard says, if you have to implement references how you would have written compiler to implement that.
Again, you somehow seem to think that compiler optimization is somehow invalid or unfair. It is not; it is the business of the compiler. The compiler is perfectly allowed to optimize references away in the generated code if it doesn't change the meaning of the program. In some cases, it is very difficult to do so, but in others it is perfectly possible, and desired behavior.
Gatik G wrote: I would like to make a point over here that Concept of having an Alias which will not take any space, if it would have been the case, there is no reason why "C" language skips that. everybody want to save space using aliases, isn't it ?
What does the "C" language have to do with this? We are discussing C++, are we not? Have you even bothered to read the Standard? Do you have any other articles that back up what you are trying to say? Will you at least attempt to define "aliasing" for us, because your article is hopelessly confused without that definition (though it's possibly hopelessly incorrect if you do define it as most developers probably would).
regards,
Jeff
|
|
|
|
|
jefito wrote: 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'
I am in agreement with you Jeff.
In fact, I just checked out what Marshall Cline says about references in the C++ FAQ Lite at http://www.parashift.com/c++-faq-lite/references.html . There he states
quote :
[8.1] What is a reference?
An alias (an alternate name) for an object.
References are frequently used for pass-by-reference:
<sample cut>
End Quote
AAR
|
|
|
|
|
It looks like both points of view have their good arguments.
The easiest way to find the truth is, of course, to examine the compiler's code. But even in this case, I believe, behavior mostly depends on optimization options.
However, both (clever and experienced, provided by author and commetators) arguments result to this conclusion:
when there is no need in storing any data (i.e., use memory) for the reference - it is just an alias for another variable. The compiler uses it as an abstract compile-time essence. Working with it, it can optimize its usage, just replace it with referenced variable address, or use it as-is (then it becomes a real essence).
In case, when memory is needed (e.g., forced by a programmer, using in a Class, etc..) in most cases "* const" is used.
So, the source of the arguing here is based just on some wrong statements:
"reference is not an alias" - WRONG, CORRECT: "reference can be just an alias (when it is enough)"
"reference is a constant pointer" - WRONG, CORRECT: "reference functionality can be implemented using "const pointer" when it requires memory space"
So, a smart coder should NOT rely on any of that two stated facts, and make conclusions based on his current code and compiler realization.
modified 8-Apr-21 14:38pm.
|
|
|
|
|
To the author: the article is a good intro, but the proof that references occupy their own memory in the machine, i.e. not aliases, is insufficient, and in fact is wrong in certain cases (at least in case of gcc):
For example:
int main()
{
int val = 3;
int &ref = val;
int *const ptr = &val;
fprintf(stdout, "This is the address of val: %d\n", &val); //#1
fprintf(stdout, "This is the address of ref: %d\n", &ref); //#2
fprintf(stdout, "This is the address of ptr: %d\n", &ptr); //#3
class Test
{
double &i; // double *const i;
double &j; // double *const j;
double &k; // double *const k;
};
fprintf(stdout, "This is the size of Test: %d\n", sizeof(Test));
return EXIT_SUCCESS;
}
fprintf statements #1 and #2 will print the same value. #3 will print a different value (with gcc).
This proves that references are aliases, syntactic objects to be resolved at compile-time. Pointers, on the other hand, are physical variables and either may or may not be optimized away during compilation.
The fact that the "Test" class has size 12, doesn't mean that reference types have sizes. It merely indicates that in that particular situation the compiler could not resolve the aliases at compile time, so it assumed that the references will be initialized at construction time (run time). Thus, it *had to turn* those aliases into constant pointers.
Check it with VC++ compiler to confirm/reject my take on the issue.
By the way, notice that the members of "Test" are references to double precision floating point type variables. I did it so that it's clear that the compiler doesn't resolve references into actual POD types, but instead resolves them into pointers - exactly what you try to convey in your article.
-Ilya
|
|
|
|
|
ilya l wrote: fprintf statements #1 and #2 will print the same value. #3 will print a different value (with gcc).
That's because you have &ptr and not &*ptr or ptr in statement #3.
ilya l wrote: The fact that the "Test" class has size 12, doesn't mean that reference types have sizes. It merely indicates that in that particular situation the compiler could not resolve the aliases at compile time, so it assumed that the references will be initialized at construction time (run time). Thus, it *had to turn* those aliases into constant pointers.
Using this code:
#include <iostream><br />
<br />
struct Test<br />
{<br />
double & x_;<br />
double & y_;<br />
Test (double & x, double & y) : x_(x), y_(y) {}<br />
};<br />
<br />
int main ()<br />
{<br />
double a = 0, b = 1;<br />
Test test (a, b);<br />
std::cout << "size of Test is " << sizeof(Test) << std::endl;<br />
std::cout << "size of test is " << sizeof(test) << std::endl;<br />
return 0;<br />
}
MSVC2005 printed 8 in both cases. Are you saying that gcc would print 16 on the second line?
Sure, compilers generate the same code for references and const pointers. But why would i care about that? All i need to know is that in the context of my source code, reference is an alias of some object and that it can't be NULL (so there is no need for asserts to check that).
|
|
|
|
|
About &*ptr: *ptr resolves to val. &val is the address of the actual object. So what?? My goal was to point out that "ptr" is a physical variable, and "ref" is somewhat more exotic, not possessing an actual memory location whether you apply compiler optimizations or not.
Regarding the "Test" class. No, Paulius: I am *not* saying that sizes of Test or test are supposed to be 16 (in gcc). I gave that example with the "Test" class merely to *support* the author's general point regarding references not being actual types. I just deemed his example with ints (whose sizes are the same as "int *") didn't illustrate his point strong enough.
So why would you care if the compiler generates same code for references and const pointers? You may happen to need to access the physical address of a reference variable (say, through an external routine), but if the address resolves to the address of the referenced variable, you do need to know about this fact so as not to modify the value of the referenced variable accidentally.
|
|
|
|
|
The original statement: "...is wrong in certain cases..." is a bit misleading. My statement refers to the author's position that references resolve into constant pointers, not the proof itself.
|
|
|
|
|