RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Manage Your STL Container's Storage with Self-swapping Idioms -3 : Page 3

Swapping the Right Way
Manual copying is tedious and error-prone. Ideally, you want to perform the trimming operation in a single statement, while avoiding the creation of a dummy container. STL containers define a specialized version of the swap() algorithm as a member function. As a rule, when you have a choice between a generic algorithm and the container's equivalent member function, prefer the latter. Instead of calling

#include <algorithm>
std::swap(vi, vi2); //works, but less efficient 

vi.swap(vi2); //recommended
The member algorithm is optimized for its container. As such, it's usually more efficient than the generic version.

A final refinement to the design also eliminates the dummy container. Simply swap the container with itself:

Let's see how it works. The expression

vector <int>(vi)
creates a temporary trimmed copy of vi. Then, the swap(vi) call is evaluated, assigning the trimmed temporary to vi, and vice versa. Finally, the temporary object is destroyed.

Here's a modified version of the previous program, now using the swap idiom:

int main()
 vector <int> vi;
 cout<<"capacity before trimming: "<<vi.capacity()<<endl;
 cout<<"size before trimming: "<<vi.size()<<'\n'<<endl;

 vector<int>(vi).swap(vi);//trim vi

 cout<<"capacity after trimming : "<<vi.capacity()<<endl;
 cout<<"size after trimming : "<<vi.size()<<endl;
As expected, the output is:

capacity before trimming: 100
size before trimming: 1

capacity after trimming: 1
size after trimming: 1

Emptying a Container
Emptying a container raises a similar problem. The clear() member function destroys the currently stored elements and resets the container's size to 0. However, it doesn't change the container's capacity. Consider:

vi.reserve(100); //enforce a capacity of 100
vi.push_back(5); //size is 1
vi.clear(); //size is 0, but the capacity is unchanged
cout<<"capacity: "<<vi.capacity()<<endl; //output: 100
cout<<"size: "<<vi.size()<<'\n'<<endl;//output: 0
To force a container to release both its elements and capacity, use a slightly different version of the swap idiom. Instead of swapping a container with a temporary copy of itself, swap it with an empty temporary:

vector<int>().swap(vi);//sets vi's size and capacity to 0

Danny Kalev is a certified system analyst and software engineer specializing in C++. He was a member of the C++ standards committee between 1997 and 2000 and has since been involved informally in the C++0x standardization process. He is the author of "The ANSI/ISO Professional C++ Programmer's Handbook" and "The Informit C++ Reference Guide: Techniques, Insight, and Practical Advice on C++."
Email AuthorEmail Author
Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date