Home arrow C++ arrow Page 6 - Temporary Variables: Keep Your Values Close, and Your References and Pointers Even Closer
C++

Temporary Variables: Keep Your Values Close, and Your References and Pointers Even Closer


As you know, in programming C++, it is much better to return a reference to an object than it is to return that object by value. As we will see in this article, it is also much better to pass a function parameter by reference than it is to pass it by value. But there are exceptions to this, as Jun Nakamura explains.

Author Info:
By: J. Nakamura
Rating: 5 stars5 stars5 stars5 stars5 stars / 11
September 26, 2005
TABLE OF CONTENTS:
  1. · Temporary Variables: Keep Your Values Close, and Your References and Pointers Even Closer
  2. · To pass or not to pass by value
  3. · Const-Correctness
  4. · Call optimization
  5. · Examining possible dangers
  6. · The cost of implicit conversion

print this article
SEARCH DEVARTICLES

Temporary Variables: Keep Your Values Close, and Your References and Pointers Even Closer - The cost of implicit conversion
(Page 6 of 6 )

C++ functions are "friendly" enough to take any object that can implicitly be converted to the parameter it accepts according to its declaration. These conversions can only be made on parameters passed by value or by const reference because these are the only ones that are under full control of the compiler.

Let’s extend the code we have been using to test object slicing. First, here is a simple class we will call Empty:

class Empty {
public:
 Empty() { (void)printf(“Empty object created.\n”); }
        void foo() const { (void)printf(“Empty::foo() called.\n”); }
};

Next we add a conversion constructor to our Base class. This is a constructor that can be called with an argument that is used to convert to the object that is about to be constructed.

class Base {
public:
 Base() {
      (void)printf(“Base created.\n”);
        }
      Base(Empty const &other) {
      (void)printf(“Base created from Emtpy object.\n”);
 }
 ~Base() {
(void)printf(“Base destroyed.\n”);
        }
 ...
};

Now we can visualize the application of the conversion constructor:

(void)printf(“Implicit Conversion test.\n”);
Empty empty_obj;
(void)printf(“calling CallByValue()\n”);
CallByValue(empty_obj);
(void)printf(“calling CallByReference()\n”);
CallByReference(empty_obj);

 

Running this code yields the following result:

Implicit Conversion test.
Empty object created.
calling CallByValue()
Base created from Empty object.
Base::foo() called.
Base destroyed.
calling CallByReference()
Base created from Empty object.
Base::foo() called.
Base destroyed.

The conversion constructor has made it possible to use the two functions that accept a Base class by passing an Empty object, either by value or by const reference. This was possible because the compiler constructs a temporary object that is a conversion of the object passed in. If you remove the const modifier in the CallByReference function declaration, the compiler will complain that it cannot convert an Empty object to a Base reference simply because it is not possible to map Empty onto Base directly… only through implicit conversion.

The Microsoft compiler in this case will complain:

Error C2664: ‘CallByReference’ : cannot convert parameter 1 from
‘Empty’ to ‘Base &’ - A reference that is not to ‘const’ cannot be bound to a non-lvalue.

We can conclude that when a function parameter utilizes a const reference, there is the possibility that an object passed into this function will be implicitly converted. So passing by value might facilitate slicing, which has unpleasant side-effects… but when using const references, we might facilitate the creation and destruction of a temporary variable.

Of course this example using a Base and Empty class is very hypothetical, but if you use the STL you have probably used conversion constructors already.

 It is why you can use foo(“some text”) with a function declaration like:

void foo (std::string const &label);

The std::string has a conversion constructor that accepts a char const*… which is very useful; just not free.

It wouldn’t be me writing these articles if I could not find a way to add insult to injury.  So how about returning a const reference from a function that was passed to that const reference?

Here is a nasty change to the CallByReference function:

Base const& AnotherCallByReference(Base const &obj);

You should realize now that this function might return a const reference to a temporary object (!). This temporary object is bound to be destroyed (rather) sooner or later… invalidating the reference to it.

As always… not everything is at it may seem to be.

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.

blog comments powered by Disqus
C++ ARTICLES

- Intel Threading Building Blocks
- Threading Building Blocks with C++
- Video Memory Programming in Text Mode
- More Tricks to Gain Speed in Programming Con...
- Easy and Efficient Programming for Contests
- Preparing For Programming Contests
- Programming Contests: Why Bother?
- Polymorphism in C++
- Overview of Virtual Functions
- Inheritance in C++
- Extending the Basic Streams in C++
- Using Stringstreams in C++
- Custom Stream Manipulation in C++
- General Stream Manipulation in C++
- Serialize Your Class into Streams in C++

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 

Developer Shed Affiliates

 




© 2003-2017 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials