在remove_if谓词中调用delete是否安全



我有一个矢量

std::vector<Object*> objects;

还有一种方法,如果发现物体,就会将其移除:

void Remove(Object *o)
{
objects.erase(
std::remove_if(
objects.begin(), objects.end(),
[&o](Object *_object) {
if (o == _object)
{
delete _object;
return true;
}
return false;
}
),
objects.end()
);
}

这安全吗?我不应该呼叫delete吗?但是erase会替我呼叫delete吗?我有点困惑。这会使迭代器无效还是会泄漏内存?

这会使迭代器无效或泄漏内存吗?

内存不会被单独的代码位泄露;它会被完整的程序泄露必须有人负责交易,但这里没有发生并不意味着根本不会发生Not在此处调用delete不";泄漏存储器";;泄漏内存的是整个程序。像这样的代码不能独立存在。

除非遵循既定模式,否则很难弄清楚责任在哪里。这就是像std::unique_ptr<T>std::shared_ptr<T>std::weak_ptr<T>这样的工具存在的原因。请使用它们。

迭代器不会失效。迭代器在容器的元素上迭代,这些元素本身就是指针。delete不会影响与其一起使用的指针。delete影响指向内存。

erase会为我调用delete吗?

否。

这安全吗?

如果任何其他代码可能尝试从容器中delete指向相同的元素,则类似的代码有双重释放(未定义行为(的风险。

同样,这不是局部风险,而是整个项目的风险。

同样,在整个程序上下文中计算内存管理通常是困难的。请根据情况,以适当的方式使用标准库工具,如std::unique_ptr<T>std::shared_ptr<T>std::weak_ptr<T>。关于C++中内存管理的正确教程超出了堆栈溢出问题的范围。

来自std::remove_if

UnaryPredicate必须满足Predicate的要求。

然后:

函数对象pred不应通过去引用迭代器应用任何非常量函数。此函数对象可以是指向函数的指针,也可以是具有适当函数调用运算符的类型的对象。

(应该可以在同一元素上调用谓词两次(。

您的谓词不尊重该要求,因此代码是不安全的。

保持您的逻辑,您可以使用std::partition:

void Remove(/*const*/ Object *o)
{
auto it = std::partition(objects.begin(), objects.end(),
[&o](const Object* object) { return o != object; }
);
for (auto it2 = it; it2 != objects.end(); ++it2) { delete *it2; }
objects.erase(it, objects.end());
}

但是使用智能指针(如std::unique_ptr(因此objects将是std::vector<std::unique_ptr<Object>>而不是std::vector<Object*>((将简化代码:

void Remove(/*const*/ Object *o)
{
objects.erase(
std::remove_if(
objects.begin(), objects.end(),
[&o](const std::unique_ptr<Object>& object) {
return o != object.get();
}
),
objects.end()
);
}

最新更新