Using inserters

When calling standard functions on containers, we should pay attention on memory issues. When we need the standard function to allocate memory we should explicitely require this using back_inserter, front_insert, or inserter (specifying where).

For example, consider this function:

int square(int value)
{
return value * value;
}

An this vector that represents our input data:

std::vector<int> vi;
vi.reserve(5);

for(int i = 0; i < 10; ++i)
vi.push_back(i);
dump(vi);

We are about to create a modified copy of the input data in a second array, using the standard function transform(). To represent the position where to put the data in the ouput vector we use the back_inserter():

std::vector<int> vr;
vr.reserve(vi.size());
std::transform(vi.begin(), vi.end(), std::back_inserter(vr), square);
dump(vr);

If the output is a list, we could decide to push the data at its beginning, causing an inversion in the sequence:

std::list<int> lr;
std::transform(vi.begin(), vi.end(), std::front_inserter(lr), square);
dump(lr);

Considering again a vector, this time not an empty one, like:

std::vector<int> vr2;
vr2.reserve(vi.size() + 2);
for(int i = 0; i < 2; ++i)
vr2.push_back(999);
dump(vr2);

We could want to put the data in the middle:

std::vector<int>::iterator it = vr2.begin() + vr2.size() / 2;
std::transform(vi.begin(), vi.end(), std::inserter(vr2, it), square);
dump(vr2);

For more details on the inserters, have a look at Item 30 in Effective STL, one of the Effective C++ book series by Scott Meyers.

No comments:

Post a Comment