Я позволю себе переписать код:
class ByReference: public std::unary_function<bool, DistanceNode>
{
public:
explicit ByReference(const Reference& r): mReference(r) {}
bool operator()(const DistanceNode& node) const
{
return node.getReference() == r;
}
private:
Reference mReference;
};
typedef std::vector< std::vector< DistanceNode > >::iterator iterator_t;
for (iterator_t it = dl.begin(), end = dl.end(); it != end; ++it)
{
it->erase(
std::remove_if(it->begin(), it->end(), ByReference(tmp)),
it->end()
);
}
Почему?
- Первый цикл (
externIterator
) выполняет итерацию по всему диапазону элементов, никогда не изменяя сам диапазон, для этого и нужен for
, так что вы не забудете увеличить его (предположительно, for_each
будет быть лучше, но синтаксис может быть неудобно)
- Второй цикл сложен: просто говоря, вы фактически обрезаете ветвь, на которой сидите, когда вызываете
erase
, что требует прыжков (используя возвращаемое значение). В этом случае операция, которую вы хотите выполнить (очистка списка в соответствии с определенными критериями), как раз и предназначена для идиомы remove-erase
.
Обратите внимание, что код можно было бы привести в порядок, если бы в нашем распоряжении была настоящая лямбда-поддержка. В C ++ 0x мы бы написали:
std::for_each(distanceList.begin(), distanceList.end(),
[const& tmp](std::vector<DistanceNode>& vec)
{
vec.erase(
std::remove_if(vec.begin(), vec.end(),
[const& tmp](const DistanceNode& dn) { return dn.getReference() == tmp; }
),
vec.end()
);
}
);
Как вы можете видеть, мы не видим больше никакого увеличения / разыменования итератора, все это заключено в специальные алгоритмы, которые гарантируют, что все обрабатывается соответствующим образом.
Я предоставлю вам синтаксис, который выглядит странно, но я думаю, это потому, что мы еще не привыкли к нему.