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