Channels ▼
RSS

C/C++

3 Most Useful Library Features of C++0x


One of the most important features in C++0x is one that many users will never use directly: the notion of moving a value from one place to another.

To see why this feature is so important, let's start by creating a string variable and then copying it:

string s = "I am a string!";
 string t = s;        // Make a copy of s

In order to make t into a copy of s, it is necessary to copy the characters that s contains. The reason, of course, is that the program might change the value of one of these variables, and that change must not affect the value of the other variable. Moreover, the program must allocate memory to contain the copy of s's characters. Allocating and freeing dynamic memory can be surprisingly slow; it is not unusual for programs to spend more time allocating and deallocating memory than manipulating that memory's contents.

The problem gets worse when we're dealing with containers of strings. For example, calling push_back on a vector<string> may have to copy each string, which in turn must copy each character of each string, together with all the memory allocation and deallocation those copies imply.

In order to see how C++0x has done away with much of this memory manipulation, we're going to start by looking at std::move, which is the part of this feature that usually lives behind the scenes as part of the library. Even if you never use std::move directly, this quick look will help you understand what goes on when you use a part of the library that does use it.

Suppose you knew that the variable s (which we defined earlier) would not be used again after you used it to initialize t. In that case, you wouldn't care what value s had afterward, as long as the value could be destroyed when s went out of scope. In such a case, C++0x enables you to write

string t = std::move(s);   // "Steal" state from s 

The std::move function simply returns its argument, but with some type magic that we'll describe in the next article. In effect, std::move is a marker that says that you do not intend to look at that argument's value again except to destroy it. Code that uses the result of std::move is permitted to "steal" the value of std::move's argument. For example, the string library can arrange to steal the resources inside s to use as t's initial value. This description is intentionally vague; our next article will fill in some more details. For now, there are two points to remember:

  1. Using std::move(s) to initialize t allows t to "steal" s's value without copying it; after the call to std::move, the value in s may not be used
  2. As a result, the program can often avoid the overhead of allocating memory for a duplicate of s, copying s's characters, and then freeing the memory.

Opportunities to use std::move arise surprisingly often in libraries. For example, to exchange the values of s and t, we might write

{ string temp = std::move(s);
   s = std::move(t);
   t = std::move(temp); }

After this code has executed, s and t have each others' former values, and the variable temp has first been given the original value of s, then an indeterminate value; and finally temp has been destroyed.

Of course, this code does what the standard library does with its swap algorithm:

std::swap(s, t);

which is why we say that there is often no need to use this feature directly. In effect, whenever you use std::swap, you're really using std::move.

Other parts of the C++0x library now use std::move too. One important example is as part of increasing the size of a vector. For example, when a vector grows as a result of calling push_back or insert, the C++0x library moves the vector's elements instead of copying them and then destroying the originals. As a result, when you call push_back on a vector<string>, C++0x avoids having to copy any of the characters in the strings that constitute the vector's elements. This avoidance can easily make such operations orders of magnitude faster in C++0x than in C++98.

Another case in which the library moves elements rather than copying them is in algorithms such as remove. These algorithms do not change the number of elements of the containers on which they act; instead, they return an iterator that refers to the just past the end of the part of the container that contains the elements we want. For example, we might remove all of the empty strings from a vector<string> named v by writing

// auto was explained in <a href="http://drdobbs.com/cpp/231002092">http://drdobbs.com/cpp/231002092</a>
auto it = remove(v.begin(), v.end(), "");
v.erase(it, v.end());

The call to remove moves the nonempty strings (i.e. those not equal to "") to the beginning of v, then returns an iterator that refers to the first element of v (if any) that is not part of the result. The elements between it and v.end() no longer have useful values, so the second line of this example gets rid of them. By moving, rather than copying, the nonempty elements of v to the beginning, the C++0x library allows examples such as this one to run much faster than the C++98 library allows, without the user needing to rewrite any code.

Incidentally, there are some classes, such as ostream in the I/O library, that cannot be copied. In C++0x, we still cannot copy these types, but now we can move them. This property makes it possible in C++0x to create a vector of objects of such classes, so long as you take pains never to ask the library to do something that would require copying, rather than moving, a vector element.


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.
 

Comments:

Video