dcsimg
LinkedIn
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

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


advertisement
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 
use:

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:


vector<int>(vi).swap(vi);
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;
 vi.reserve(100); 
 vi.push_back(5); 
 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