我有一个对象列表:
struct reply_t {
unsigned int xid;
char *buf;
};
std::list<reply_t> > replies;
我想删除该列表中的一些元素(xid <= confirmed_id
)。我喜欢std :: remove_if
提供的简洁。
remove_if(replies.begin(), replies.end(),
[&confirmed_id](const reply_t &arg) { return arg.xid <= confirmed_id; });
问题是这不会释放buf
(在其他地方分配)。有没有一种优雅的方式来处理这个?它是否像在对象析构函数中添加free(buf)一样简单?
答案 0 :(得分:5)
你可以为reply_t实现一个删除buf的析构函数:
struct reply_t {
unsigned int xid;
char *buf;
~reply_t() { delete buf; }
};
答案 1 :(得分:2)
这段代码是C和C ++的邪恶沙拉。
在C ++中,每个类都应该有一个构造函数来累积对象所需的东西,析构函数释放对象在其生命周期中获得的任何资源。
您提供的结构是一个纯C结构,它不与C ++容器一起使用,也不与C ++语言哲学一起使用。它不能清理&#34;垃圾&#34;它会产生泄漏。
使用C ++语言调用的构造函数 - accumulates-Destructor-releases RAII 成语。
你的对象应该有一个合适的构造函数和析构函数:
Listview
答案 2 :(得分:2)
正如其他人所说,是的,您可以添加析构函数来执行删除操作。他们遗漏的是,当你这样做时,你必须也实现一个复制构造函数和赋值运算符。否则,当您将其中一个对象复制到列表中时,复制的对象将删除缓冲区,然后该对象的副本也将删除缓冲区。这是个坏消息。或者,如同建议的那样,使用std::string
代替char*
;这样,编译器生成的拷贝构造函数和赋值运算符就会做正确的事。
答案 3 :(得分:0)
Here is a possible implementation of remove_if
template<class ForwardIt, class UnaryPredicate>
ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p)
{
first = std::find_if(first, last, p);
if (first != last)
for(ForwardIt i = first; ++i != last; )
if (!p(*i))
*first++ = std::move(*i);
return first;
}
所以也许您可以通过此代码实现,但是您应该通过为您的类添加析构函数或使用std :: string而不是char *来实现它。
remove_if(replies.begin(), replies.end(),
[&confirmed_id](reply_t &arg)
{
if(arg.xid <= confirmed_id)
{
delete[] arg.buf;
arg.buf = nullptr;
return true;
}
return false;
});