What's Wrong With This Code? Volume #6
The STL
by Chris Uzdavinis
A programmer has a collection of pointers to objects of the
following class A.
class A
{
public:
void do_something();
bool is_even() const;
};
Here is the global typedef and declarations for a couple of vector containers, v1 and v2.
typedef std::vector<A*> V;
V v1, v2 ;
Given the above declarations, find what can be improved about the
following code snippets. Some have incorrect behavior, others are
just inefficient. Some simply have better ways to be implemented.
Others have POTENTIAL to cause problems but don't always do so.
Assume v1 and v2 are global, for simplicity, and that the pointer
elements are never null. (If you're careful you can make such a
guarentee, and we are assuming it here.)
Finally, assume each code snippit is independent from all the
others. That is, code in item #1 doesn't affect code in item #2,
neither affect #3, and so on.
Question #1:
// assign contents of v2 to v1
v1 = v2;
What can potentially go wrong here? What considerations should
you make when doing this?
Question #2:
// delete the element in position 5
void f()
{
if (v1.size() > 5)
{
delete v1[5];
}
}
Why is calling f() most likely going to lead to a program crash?
Question #3:
// copy v1 into v2
void f()
{
std::copy(v1.begin(), v1.end(), v2.begin());
}
How can this blow up?
Question #4:
// find an element and remove it from container.
// assume the caller keeps a reference to a so it
// isn't leaked.
void f(A *a)
{
V::iterator i = std::find(v1.begin(), v1.end(), a);
if (i)
{
v1.erase(i);
}
}
What is the subtle bug here that has serious consequences?
Question #5:
// count all a's in the range that are "special"
extern bool is_special_value(A *);
int count_special_values(V const & v)
{
int count = 0;
V::iterator i = v.begin();
while (i != v.end())
{
if (is_special_value(*i))
{
++count;
}
i++;
}
return count;
}
Why doesn't this compile? Once it compiles, what can be improved
about this function?
Question #6:
// erase all members of v1
void f()
{
V::iterator i;
V::iterator end = v1.end();
for (i= v1.begin(); i != end; ++i)
{
v1.erase(i);
}
}
What's wrong with the assumptions in this code? How can this be made
more efficient?
Question #7:
// remove even-valued entries from the list
typedef std::list<A*> List;
void f(List & lst)
{
// now operate on the list
List::iterator i = lst.begin();
while (i != lst.end())
{
if ((*i)->is_even())
{
lst.erase(i);
}
++i;
}
}
What common mistake is the programmer making?
Question #8:
std::mismatch(v1.begin(), v2.begin(), v2.end());
Something is wrong with this call that has undefined runtime behavior
(though you can reasonably expect a crash.) What?
Question #9:
// call do_something_with() for each item in v1 that is not even
extern void do_something_with(A*);
void f()
{
V::iterator i = v1.begin();
while (i != v1.end())
{
if ((*i)->is_even())
{
// skip this item
++i;
}
do_something_with(*i);
i++;
}
}
What bugs are in this code? It not only contains logic bugs (it
doesn't do what the documentation (comment at top) says), but it
has iterator problems as well. How many can you find?
|