C++
  Home arrow C++ arrow Page 4 - Temporary Variables: Temporaries Are Not N...
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Mobile Linux 
App Generation ROI 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
C++

Temporary Variables: Temporaries Are Not Necessarily Evil
By: J. Nakamura
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 1
    2005-10-03

    Table of Contents:
  • Temporary Variables: Temporaries Are Not Necessarily Evil
  • Binding a reference to a temporary object
  • Death by Returned const Reference
  • It can be Good to Return by Value

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    Temporary Variables: Temporaries Are Not Necessarily Evil - It can be Good to Return by Value


    (Page 4 of 4 )

    We started this examination of temporary variables with looking at the extra overhead they can incur and how much more efficient the use of references can be. But the use of references brought its own dangers, like the possibility of returning handles to temporary objects that were constructed implicitly by the compiler.

    So while references can come in very handy and bring us better efficiency, there are situations where we do not want to use them. One of these situations can be made clear by looking at the current state of our FindClosest function:

    Enemy& FindClosest(list<Enemy> &enemies, Player const &player) {
     // cannot return an enemy when list is empty
     assert(!enemies.empty());

     list<Enemy>::iterator closest;
     float min_sqdistance=FLT_MAX;

     list<Enemy>::iterator nmeIt;
     for (nmeIt=enemies.begin(); nmeIt!=enemies.end(); nmeIt++) {
      
    Vector3 nme2ply=player.GetPos() – nmeIt->GetPos();
      float sqdist=nme2ply.SquaredLength();
      if (sqdist < min_sqdistance) {
       closest=nmeIt;
       min_sqdistance=sqdist;
      }
     }
     return *closest;
    }

    Now we can justify the return of an Enemy by reference and the need to return the Enemy list by reference and the Player object by const reference. There is however a function used in there that returns its result by value rather than by reference:

    class Vector3 {
     float mX, mY, mZ;
    public:
          ...
          Vector3 const operator– (Vector3 const &rhs) const {
      return Vector3(mX-rhs.mX, mY-rhs.mY, mZ-rhs.mZ);
          }
          ...
    };

    As to why this function returns a Vector3 const, I would like to refer you to one of my other articles about Const Correctness.

    To determine the vector from point A to point B, we subtract point A from point B. The positions of the enemies and the player are relative to the world’s origin, so each position can be considered to be a vector from this origin to reach that location.

    As a side note, please observe that the Vector subtraction operator could have been declared the following way:

    inline Vector3 const operator- (Vector3 const &lhs,
         Vector3 const &rhs) {
     return Vector3(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z);
    }

    But this would have only been beneficial if we expected other objects to be able to implicitly be converted to Vector3 by the compiler. Since this is not the case (in a video game you actually want to avoid this because the Vector3 class is heavily used and temporary objects should be avoided as much as possible), it is fine to embed the subtraction operator in the class itself.

    Returning to our main topic, when we compare the squared length of each resulting vector, we can determine which enemy is closest to the player.

    The subtraction operator has to return a new object, because the operator is allowed to modify neither the left hand side nor the right hand side of the equation. Imagine what the effect would be if the call A = B – C would yield different results each time it was called subsequently! Nobody would want to use your math library.

    The only way to circumvent the return of a new value would be to implement the subtract and assign operator:

    Vector3& operator-=(Vector3 const &rhs)
    {
     mX -= rhs.mX;  mY -= rhs.mY;  mZ -= rhs.mZ;
     return *this;
    }

    This will not allow us to construct a vector between an Enemy and the Player with this intuitive statement:

    Vector3 nme2ply=player.GetPos() – nmeIt->GetPos();

    But we would have to write this instead:

    Vector3 nme2ply(player.GetPos());
    nme2ply -= nmeIt->GetPos();

     

    You might still argue that this is better, since the intuitive statement needs the construction and destruction of a temporary object, and the latter statement doesn’t. Luckily the C++ Standard tells us that we can help compilers to optimize the temporary variable away, which means that both statements can be as efficient, just not as intuitive.

    In the next article we shall take a look at how we can facilitate Return Value Optimization and which other (though smaller) optimizations can be made to the FindClosest function.

    At this point I hope that it is clear that the compiler can create a lot of unseen objects behind the scenes and that you understand why this is needed.

    References might look like a secure rescue, but they too can turn on you in the most unexpected ways.

    Just remember what is going on inside the language and how the compiler will deal with it (according to the C++ Standard) and you will be fine.

    Know what you are doing so your code does what you think it should.


    References

     [Meyers] – Scott Meyers

    “Effective C++” – ISBN 0201924889

    [Sutter] – Herb Sutter

    “Exceptional C++” -  ISBN 0201615622

    [Niebler] – Eric Niebler

    “Conditional Love: FOREACH Redux”

    http://www.artima.com/cppsource/foreach.html

    [Kernighan] – Brian Kernighan (interview)

    http://www-2.cs.cmu.edu/~mihaib/kernighan-interview/


    DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

     

    C++ ARTICLES

    - Paths and Files
    - Directories in C++
    - Focusing on C++ Files
    - Const Correctness in C++
    - Manipulating Streams and Files with C++
    - Streams and Files
    - Multiplying Large Numbers with Karatsuba`s A...
    - Large Numbers
    - Dijkstra`s Shunting Algorithm with STL and C...
    - Brief Introduction to the STL Containers
    - The Standard Template Library
    - Templates in C++
    - C++ Programmer Alerts
    - C++ Programming Tips
    - First Steps in (C) Programming, conclusion






    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 3 hosted by Hostway
    Stay green...Green IT