Jump to content

  • Log In with Google      Sign In   
  • Create Account


Is this a VS compiler bug with references?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
4 replies to this topic

#1 Raptisoft   Members   -  Reputation: 171

Like
0Likes
Like

Posted 20 January 2014 - 09:31 AM

Hi all,

 

I ran into a funny problem today... using visual studio 2010, I did this:

Quad& aQuad=aSprite1.GetTextureQuad();
printf("Quad Center: %f,%f",aQuad.Center().mX,aQuad.Center().mY);

//
// Re-use the reference...
//
aQuad=aSprite2.GetTextureQuad();
printf("Quad Center (2): %f,%f",aQuad.Center().mX,aQuad.Center().mY);


....and I get the same value for both printfs-- the value that came from aSprite2.  It's like it completely discarded the referenced data to aSprite1.

 

If I change it to this:

Quad& aQuad=aSprite1.GetTextureQuad();
printf("Quad Center: %f,%f",aQuad.Center().mX,aQuad.Center().mY);

//
// Use a whole new reference!
//
Quad& aQuad2=aSprite2.GetTextureQuad();
printf("Quad Center (2): %f,%f",aQuad2.Center().mX,aQuad2.Center().mY);

...Then it works as expecting, printing out two different center points for two different quads.

 

So my question is, am I running into a compiler bug here, or is this a known shortcoming of references that I've just never heard of until this point?

 

Thanks!


Edited by Raptisoft, 20 January 2014 - 09:34 AM.


Sponsor:

#2 BitMaster   Crossbones+   -  Reputation: 3784

Like
4Likes
Like

Posted 20 January 2014 - 09:41 AM

References can only be initialized once. Ever.

In your first code sample aQuad is initialized to whatever reference aSprite1.GetTextureQuad() returns (are you absolutely certain, by the way, that you are not running into undefined behavior here? Code like that always makes me go 'oh-oh'). The second assignment then calls the copy constructor of Quad to copy the content of aSprite2.GetTextureQuad() into the reference (and by implication overwrites aSprite1).

Assuming for a moment your code used pointers instead of references, you are doing this:
Quad* aQuad=aSprite1.GetTextureQuad();
printf("Quad Center: %f,%f",aQuad-<Center().mX,aQuad->Center().mY);

//
// Re-use the reference...
//
*aQuad= *aSprite2.GetTextureQuad();
printf("Quad Center (2): %f,%f",aQuad->Center().mX,aQuad->Center().mY);
References are really not intended for what you try to make them do.

#3 Raptisoft   Members   -  Reputation: 171

Like
0Likes
Like

Posted 20 January 2014 - 11:11 AM

Thanks!  So it was just something I didn't know.  I think this is the first time I ever even tried to initialize one twice (I tend to treat references a pointers that can never be null).

 

However, just to be clear-- I WAS trying to overwrite the contents-- after I was done with them.  I was just re-using a variable.  I expected the contents of the Quad& reference to be filled in the same way that *Quad's contents would have been filled-- procedurally as the program went along.



#4 SeanMiddleditch   Members   -  Reputation: 4739

Like
0Likes
Like

Posted 20 January 2014 - 11:43 AM

Thanks!  So it was just something I didn't know.  I think this is the first time I ever even tried to initialize one twice (I tend to treat references a pointers that can never be null).


While I do recommend understanding that C++ references are in every real-world implementation basically just pointers that can't be assigned null (though you can get a null reference with a small bit of trickery), I also highly recommend understanding that conceptually that's not what a reference is. It's an alias for another object. There's a much bigger and better reason why C++ has references besides being non-nullable pointers.
 

However, just to be clear-- I WAS trying to overwrite the contents-- after I was done with them.  I was just re-using a variable.  I expected the contents of the Quad& reference to be filled in the same way that *Quad's contents would have been filled-- procedurally as the program went along.


That is how they should behave. The code as you posted it (if I make a few assumptions about the rest of the code) should output what you expected. Get the first quad, print those values, _then_ overwrite it with the second quad's values, then write those new values.

But that all depends on what the return type of GetTextureQuad is. Because you're using non-const references to store the return value you might be running into undefined behavior if GetTextureQuad does not also return a reference. The compiler may be reordering the code in ways it's totally allowed to (it's allowed to do anything it damn well wants with undefined behavior) if you're writing "illegal" code. I can't say for sure that's what is happening without seeing a complete _simplified_ code example (few people are interested in reading your entire codebase) that exhibits the problem. Certainly however I've never once seen any compiler erroneously reorder code just because of a reference (in valid code), and we've been using VS2010 for years now on some _very_ big and complex game codebases.

Compile with the highest warning level and "warnings as errors" turned on. Always. It'll help catch language violations early. Even seasoned professionals (or _especially_ seasoned professionals) turn those on.


Edited by SeanMiddleditch, 20 January 2014 - 06:38 PM.


#5 Mito   Members   -  Reputation: 827

Like
0Likes
Like

Posted 21 January 2014 - 03:36 AM

Get us the declaration of aSprite1.GetTextureQuad().

 

I think your problem is that GetTextureQuad() returns by value, that would create a temporary object and then get a reference to it.

 

here's some info: http://www.herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS