我们有一些遗留代码,它返回指向堆分配对象的巨大大小列表(我们无法使用智能指针),我们将从列表中删除重复项,并从堆中删除它们。
现在,正如专家建议的那样,我想尝试std::list::unique(或forward_list::unique)而不是算法std::unique。
我在http://en.cppreference.com/w/cpp/container/list/unique中读到,在“unique”谓词中,我们不应更改对象,因此按照标准术语删除“将要被删除”的对象是否安全?
如果是这样,list::unique中的哪个对象应被视为重复项?在gnu实现中,“b”将被删除,但在http://www.cplusplus.com/reference/list/list/unique/中写道,在pred(i, i-1)中,i项将被删除,那么这种行为是否由标准指定?
在标准方面,这段代码是否正确,还是UB(未定义行为)?
现在,正如专家建议的那样,我想尝试std::list::unique(或forward_list::unique)而不是算法std::unique。
我在http://en.cppreference.com/w/cpp/container/list/unique中读到,在“unique”谓词中,我们不应更改对象,因此按照标准术语删除“将要被删除”的对象是否安全?
如果是这样,list::unique中的哪个对象应被视为重复项?在gnu实现中,“b”将被删除,但在http://www.cplusplus.com/reference/list/list/unique/中写道,在pred(i, i-1)中,i项将被删除,那么这种行为是否由标准指定?
在标准方面,这段代码是否正确,还是UB(未定义行为)?
List.sort( [] (const Val *a, const Val *b) {
return *a < *b;
});
List.unique([] (const Val *a, const Val *b) {
if (*a == *b) {
delete b; // (1) working in gcc 4.6
// or (2) delete a (elsewhere)?
return true;
}
return false;
}) ;
更新 #1
Mike的解释是最有帮助的,但现在我们正在使用这样的解决方案:
struct RawPtrEq {
bool operator()(const Val a, const Val b) { return *a == *b;}
};
auto it = adjacent_find( begin(List), end(List), RawPtrEq() );
while(it != end(li)) {
delete *it;
it = List.erase(it);
it = adjacent_find( it, end(List), RawPtrEq() );
}
pred(*i, *(i - 1))
),因此如果使用delete b
,我们将删除下一个比较中将再次引用的对象。 - Wojtek Surowkaremove_if
,它只会对每个元素应用一次谓词。 - Mike Seymour