通常的答案是:熟悉你的<algorithm>
(也是对我自己的一个好提醒);)
std::partition
是你要找的东西:std::partition(begin, end, p)
“移动”范围[begin
, end
)中不满足谓词p
的元素到范围的末尾;然后你可以把它们作为一批处理。
auto const to_be_removed = std::partition(begin(v), end(v), [](auto p){ });
std::for_each(to_be_removed, end(v), [](auto p) {
delete p;
});
v.erase(to_be_removed, end(v));
完整程序
#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
std::vector v = { new int{0}, new int{1}, new int{2} };
auto const to_be_removed = std::partition(begin(v), end(v), [](auto p){ return *p % 2 != 0; });
std::for_each(to_be_removed, end(v), [](auto p) {
std::cout << "Deleting value " << *p << "...\n";
delete p;
});
v.erase(to_be_removed, end(v));
}
现场演示
深入了解
该实现有两个主要缺陷:向量的顺序不稳定(1),可以将其分解为可重用函数(2)。
- (1)可以通过
std::stable_partition
解决。
- (2)并不难:
template<class InputIt, class UnaryPredicate, class UnaryDeleter>
InputIt delete_if(InputIt begin, InputIt end, UnaryPredicate p, UnaryDeleter d)
{
auto const to_be_removed = std::stable_partition(begin, end, std::not_fn(p));
std::for_each(to_be_removed, end, [d](auto p) { d(p) ; delete p; });
return to_be_removed;
}
template<class Container, class UnaryPredicate, class UnaryDeleter>
auto delete_if(Container& c, UnaryPredicate p, UnaryDeleter d)
{
using std::begin, std::end;
return c.erase(delete_if(begin(c), end(c), p, d), end(c));
}
用法:
delete_if(v, SomeTest, DoSomething);
现场演示
delete
原始指针只有在拥有原始指针的邪恶情况下才有意义。问题陈述并没有明确指出指针的所有权,因此你在吹毛求疵方面是_技术上_正确的。 - Max Langhof