/**
* The last blog entry I made was all about lvalue vs. rvalue references.
* I wanted to parlay that into a sweet beginners level entry example about
* C++ rvalue references.
*
* After a quick googling I found a sweet article by Hinnant, Stroustrup
* (yes, the Stroustrup), and Kozicki [1] about rvalue references entitled
* "A Brief Introduction to Rvalue References". You're probably saying to
* me, "JR, but I don't have a C++11 compiler!".
*
* If you are a newbie to C++11 and/or gcc, you may not know about the
* g++ flag to enable C++11 features. Here's a simple script to compile
* using C++11 extensions in gcc:
*
* g++ -std=c++11 main.cpp
*
* That's it. I tried this out on a simple "Hello C++11" program and everything
* seemed to work. However, a simple hello world is insufficient to test
* the C++11 features. So I want to try a simple rvalue reference example.
*/
#include <iostream>
#include <string>
#define PRINT_A_CREATION
//#define CPP_03
class A
{
public:
A()
{
#if defined PRINT_A_CREATION
std::cout << "--> A Default Constructed" << std::endl;
#endif
}
/**
* We can output when we perform a copy.
*/
A(A const& a)
{
#if defined PRINT_A_CREATION
std::cout << "--> A Created via Copy Constructor!" << std::endl;
#endif
this->value = a.value;
this->description = a.description;
}
A& operator=(A const& a)
{
#if defined PRINT_A_CREATION
std::cout << "--> A uses Assignment Operator!" << std::endl;
#endif
this->value = a.value;
this->description = a.description;
return *this;
}
int value;
std::string description;
/**
* We are going to output the contents of this as a const sometimes,
* so make sure we use the const qualifier!
*/
void dump() const
{
std::cout << description << " - " << value << std::endl;
}
};
/**
* To illustrate rvalue references, I want a function that returns
* a more complicated object than an int or string.
* @return an object of A by value.
*/
A ReturnByValue()
{
A a;
a.value = 12234;
a.description = "Hello C++11";
return a;
}
int main(int argc, char** argv)
{
// This is the first form where it is completely inefficient.
// ReturnByValue
A a1 = ReturnByValue();
a1.dump();
// The following is an error, because we can't take a reference
// to a temporary.
#if defined ERROR1
A& a2 = ReturnByValue();
a2.dump();
#endif
// This IS allowed by the standard [3]. I actually got served on
// this in a meeting. :)
A const& a3 = ReturnByValue();
a3.dump();
// If you want to compile this with C++03 to insure results,
// just enable the CPP_03 macro.
#if !defined CPP_03
// This is the new syntax of an rvalue reference in C++11. This
// is kind of crazy because gcc will not work without enabling
// C++11 (as documented above).
A&& a4 = ReturnByValue();
a4.dump();
#endif
// At this point I ran the example above with the macro
// PRINT_A_CREATION enabled- what shocks me about this is
// I don't see the copy constructor or assignment operator
// being invoked.
}
/**
* Sorry this was a little light on the C++ side and more elaborate about
* how to enable C++11 extensions. I hope to explore rvalue references in a little
* more detail tomorrow.
*
* In conclusion, g++ does allow us to compile C++11 code but it is still
* experimental [4]. If g++ doesn't suit your fancy you should try clang. The only
* downside to clang is its uncertain ease of availability in Windows.
*/
/**
REFERENCES
[1] - http://www.artima.com/cppsource/rvalue.html
[2] - http://linux.die.net/man/1/g++
[3] - http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const
[4] - http://gcc.gnu.org/projects/cxx0x.html
[5] - http://clang.llvm.org
*/
No comments:
Post a Comment