Быстрый способ удалить записи вектора STL из указателей
У меня есть вектор указателей, которые я хочу удалить, но перебирая вектор и вызывая delete
для каждого элемента довольно медленно. Есть ли более быстрый способ?
К сожалению, мне действительно нужно хранить указатели, поскольку я использую виртуальный суперкласс. Упрощенно, структура классов выглядит примерно так:
class VirtualSuperClass
{
protected:
SomeType m_someMember;
// ...
public:
virtual void doSomething() = 0;
};
class Subclass_1 : public VirtualSuperClass
{
protected:
SomeType m_someSubclassMember;
// ...
public:
virtual void doSomething() { /* do something*/ }
};
class Subclass_2 : public VirtualSuperClass
{
protected:
SomeType m_someOtherSubclassMember;
// ...
public:
virtual void doSomething() { /* do something else*/ }
}
В моем основном методе я заполняю вектор указателей суперкласса и вызываю функцию doSomething()
для каждого элемента.
int main()
{
std::vector<VirtualSuperClass*> vec;
vec.push_back(new Subclass_1());
vec.push_back(new Subclass_2());
vec.push_back(new Subclass_2());
vec.push_back(new Subclass_1());
// and so on, about 40,000 elements (not really done with .push_back :) ) ...
// this actually runs in an application loop
for (size_t i = 0; i < vec.size(); i++)
{
vec[i]->doSomething();
}
// ...
for (size_t i = 0; i < vec.size(); i++)
{
delete vec[i]; // <-- pretty slow for large number of elements
vec[i] = NULL;
}
vec.clear();
return 0;
}
3 ответа
Одна вещь, которую вы можете искать, это пользовательский распределитель для классов, которые вы выделяете - таким образом, вы можете эффективно получать и высвобождать память для системы в большом количестве, а не в маленьких фрагментах - это, вероятно, единственное решение для улучшения "общей" производительности этого система без ее изменения (что, учитывая ваше узкое место, безусловно, выглядит хорошей идеей;)).
Любое правильное решение сводится к delete
на каждом указателе. Поскольку вы профилировали свой код и определили, что это является узким местом, я бы искал решение, которое бы delete
в другую ветку.
Это может быть сделано:
- Создать рабочий поток, который
delete
указатели переданы в - Удалите указатели из вектора и скопируйте их в другой вектор, принадлежащий рабочему потоку.
- Начните задание рабочего потока, позвольте ему удалить указатели
Это не будет быстрее, чем ваше текущее решение, с точки зрения чистого процессорного времени (и на самом деле может быть медленнее, в зависимости от того, как вы это делаете), но это переместит тяжелую работу из вашего основного потока.
Другой метод, который может улучшить производительность, - это использовать пул памяти, в котором вы выделяете один большой необработанный буфер, а затем размещаетеnew
каждый отдельный объект в этом буфере.
Это может повысить производительность, потому что, хотя вам все еще нужно уничтожить каждый указатель, это уничтожение выполняется посредством прямого вызова деструктора, а не delete
это Это позволяет избежать необходимости обращаться к диспетчеру памяти системы, и именно в этом случае возможны улучшения производительности.
Однако у этого подхода есть существенные недостатки, и я бы не рекомендовал его ни в каких, кроме самых крайних случаях. Среди предостережений - обременительная ответственность, которую вы возлагаете на себя, чтобы управлять своей собственной памятью.