Channels ▼
RSS

C/C++

C++0x's Tools for Library Authors




How Library Authors Should Use rvalue References

Rvalue references are particularly important if you are writing a class whose objects might be put into a container such as a vector. Most readers have encountered the Rule of Three, which says that if your class has a destructor, it probably needs a copy constructor and copy-assignment operator, too. In C++0x, the Rule of Three sometimes expands to a Rule of Five:

class Foo {
// …
 Foo(); 					// Default constructor
 Foo(const Foo&);			// Copy constructor
 Foo& operator=(const Foo&);// Copy assignment
 Foo(Foo&&);				// Move constructor
 Foo& operator=(Foo&&);		// Move assignment
 ~Foo();					// Destructor
};

If your class has a destructor, you may want to write a move constructor and move assignment operator for it as well. In both cases, the move versions are permitted to change their argument's value, because the compiler will call the move constructor or move assignment operator only on rvalues. However, because even an rvalue will eventually be destroyed, the program must leave its parameter with a valid value. It doesn't matter what that value is; typically, it will be something trivial such as a null value.


If you define the move constructor and move assignment operator properly, the compiler will call it whenever it is appropriate to do so. If you don't define them, the compiler will quietly use the copy constructor and copy assignment operator.



This discussion has only scratched the surface of this vast topic. The main points to remember:

  • Rvalue references let class authors reuse the contents of objects that are about to go away instead of copying those contents and then destroying the originals.

  • This ability is particularly important for classes whose objects might be put in containers, such as vector, that move their contents from time to time; it can make an enormous difference in execution time.

  • Move operations also allow classes (such as the IO types) to say that they can be moved but not copied.

  • You indicate that a class can move its contents by defining a move constructor and move assignment operator to go along with the copy constructor and copy assignment operator.

  • The move constructor and assignment are allowed to change the contents of their source, but they must leave their source as a valid value so that when the destructor is eventually called, it doesn't crash.

  • If you don't define a move constructor or move assignment, but your class does define its own copy constructor and assignment, then the compiler will use the copy constructor and assignment. Doing so yields sensible results, but foregoes the optimization that the move versions might offer.

  • You can call std::move explicitly on an object. It returns that object as an rvalue reference, so that if you copy or assign the result of std::move, doing so will call the move constructor or assignment operator, if one exists.

Constructors Made Easier

C++0x lets you give a default initial value to a class data member:



class  Foo {
   public:
         Foo() { }
         Foo(int a): m(a) { }
         Foo(int a, int b): m(a), n(b) { }
   private:
         int a = 0, b = 0;          // New in C++0x
         std::string myName("Foo"); // New in C++0x
                // …
};

The ability to give initial values to data members such as a, b, and myName is new in C++0x. When we do so, we are saying what values we want those members to have if the constructor doesn't say otherwise. Therefore, in this example, calling Foo() initializes both a and b to 0, Foo(42) initializes a to 42 and b to 0, and Foo(42, 24) initializes a to 42 and b to 24. In all cases, myName is initialized to "Foo".


This feature is especially convenient for classes with many constructors. Adding a data member to such a class used to require adding an initializer to every constructor. Under C++0x, it is possible to add one initializer to the data member's declaration, and then change only those constructors that give that member an unusual initial value.


C++0x makes it easier to write constructors in four other ways as well: You can

  • declare a constructor as = delete to say that no one is allowed to use it.

  • declare a constructor as = default to tell the compiler to generate it even if it would not usually do so (e.g., a default constructor).

  • delegate initialization to another constructor in the class by writing a constructor initializer that passes values to that constructor 

  • write a using-declaration to copy a constructor from a base class.




If, for example, we wanted to make our Foo class movable but not copyable, we might add the following member declarations:


Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
Foo(Foo&&);
Foo& operator=(Foo&&);

and then define the move constructor and move assignment operator appropriately.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video