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

By submitting your information, you agree that devx.com may send you DevX offers via email, phone and text message, as well as email offers about other products and services that DevX believes may be of interest to you. DevX will process your information in accordance with the Quinstreet Privacy Policy.


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




Application Security Testing: An Integral Part of DevOps

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; 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++."
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date