[英]need a std::vector with O(1) erase
我很惊讶地发现vector :: erase在调用delete时移动元素。 我以为它将最后一个元素与“待删除”元素交换,并将大小减小一个。 我的第一个反应是:“让我们扩展std :: vector并重写ride()”。 但是我在许多线程中发现“ 从C ++ STL容器派生出任何真正的风险吗? ”,它可能导致内存泄漏。 但是,我没有在vector中添加任何新的数据成员。 因此,没有额外的内存可以释放。 还有风险吗?
有些人建议我们应该更喜欢组合而不是继承。 在这种情况下,我无法理解这个建议。 为什么我要浪费时间来包装包装本来不错的std :: vector类的每个函数的“机械”任务? 对于这个任务,继承确实是最有意义的-还是我错过了一些东西?
为什么不编写只执行所需功能的独立函数呢?
template<typename T>
void fast_erase(std::vector<T>& v, size_t i)
{
v[i] = std::move(v.back());
v.pop_back();
}
虽然所有归功于Seth Carnegie。 我最初使用“ std :: swap”。
微妙的问题。 您要打破的第一条准则是:“ 继承不是为了代码重用 ”。 第二个是:“不要从标准库容器继承”。
但是:如果可以保证,没有人会使用您的unordered_vector<T>
作为vector<T>
那么您很好。 但是,如果有人这样做,则无论您有多少成员,结果都可能是不确定的和/或可怕的(它看起来工作得很好,但仍然是不确定的行为 !)。
您可以使用private
继承,但是这并不能使您摆脱编写包装程序或使用大量 using
语句提取成员函数的麻烦,这几乎与组合的代码一样多(尽管少了一些)。
编辑:我的意思是using
语句是这样的:
class Base {
public:
void dosmth();
};
class Derived : private Base {
public:
using Base::dosmth;
};
class Composed {
private:
Base base;
public:
void dosmth() {return base.dosmth(); }
};
您可以使用std::vector
所有成员函数来执行此操作。 如您所见, Derived
代码明显少于Composed
代码。
在以下示例中,继承的风险:
std::vector<something> *v = new better_vector<something>();
delete v;
这将导致问题,因为您删除了没有虚拟析构函数的基类的指针。
但是,如果您总是像以下那样删除指向类的指针:
better_vector<something> *v = new better_vector<something>();
delete v;
或不将其分配到堆上就没有危险。 只是不要忘记在析构函数中调用父析构函数。
我以为它将最后一个元素与“待删除”元素交换,并将大小减小一个。
vector ::: erase在将最后一个元素移到擦除的元素时保持元素的顺序,并且不减小其大小。 由于vector实现数组,因此没有O(1)方式可以保持元素顺序并同时擦除(除非您删除最后一个元素)。
如果维护元素的顺序并不重要而不是解决方案还可以,那么最好使用其他容器(例如list ,它实现双向链接的list)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.