2015-05-21 3 views
0

У меня есть std::vector< MyObject* > my_vector; Что не пусто, и я хочу выделить и нажать определенное количество MyObject * в нем. Я знаю, сколько объектов нужно нажать. Есть ли лучший способ (оптимизированный/быстрее), чтобы сделать это, чем:Выделение векторного содержимого std с помощью динамических объектов

int object_count = 10000; 
for(int index = 0; index < object_count; index++) 
{ 
    my_vector.push_back(new MyObject()); 
} 

Как выделить в один вызове таНоса для всех MyObject, а затем тетср результата в my_vector. Любая идея?

Обновление Моя проблема - вызов новых 10000 раз. Я хочу иметь возможность выделить один большой кусок памяти и поменять память до конца my_vector.

+2

У вас есть хорошая причина для использования указателей и 'new'? С помощью 'vector ' вы можете просто использовать 'resize' (или подходящий конструктор) для добавления построенных по умолчанию объектов. –

+1

Да, потому что объекты, которые я нажимаю, являются специализациями MyObject. – Silouane

+0

@ Силуан: Хорошо, справедливо. –

ответ

3

Вы можете просто зарезервировать достаточно места в векторе, поэтому он будет выделять память только один раз. Кроме того, это хорошая практика, чтобы использовать станд :: unique_ptr <>:

std::vector<std::unqiue_ptr<MyObject> > my_vector; 
int object_count = 10000; 
my_vector.reserve(object_count); 
for(int index = 0; index < object_count; index++) 
{ 
    my_vector.push_back(std::unique_ptr<MyObject>(new MyObject())); 
} 

Update: если вы не можете использовать (или не хотят) использовать unique_ptr, просто добавьте запас в свой код, чтобы предварительно выделить Память.

Обновление 2: Насколько я понял, вы хотите избежать выделения памяти в new MyObject(). Одно из возможных решений, чтобы сделать это состоит в следующем (не предназначена для использования в режиме реального применения):

// a very simple example 
class Pool { 
public: 
    Pool() : array(new MySpecObjects[10000]), counter(10000); {} 
    MySpecObject* get() { 
    --counter; 
    return array[counter]; 
    } 
    void reset() { 
    counter = 10000; 
    } 
    MySpecObject* array; 
    size_t counter; 
}; 

static Pool* getPool() { 
    static Pool pool; 
    return pool; 
} 

std::vector<MyObject* > my_vector; 
int object_count = 10000; 
my_vector.reserve(object_count); 
for(int index = 0; index < object_count; index++) { 
    my_vector.push_back(getPool().get())); 
} 

Это упрощенный пример, это не поточно и бассейн очистит его память при завершении работы программы. Идея это похоже на flyweight gof pattern, see boost for example

Update 3: может быть, лучшим решением является использование intrusive lists здесь. Тогда все, что вам нужно сделать, это заранее выделить векторы объектов:

class MyObject : public boost::intrusive::list_base_hook<> { 
    ... 
}; 
// MySpecObject1 and MySpecObject2 inherit MyObject 
std::vector<MySpecObject1> objs1(10000); 
std::vector<MySpecObject2> objs2(10000); 
... 

typedef boost::intrusive::list<MyObject> BaseList; 

BaseList list; 
for (MyObject& ref : objs1) { 
    list.push_back(ref); 
} 
for (MyObject& ref : objs2) { 
    list.push_back(ref); 
} 

Обратите внимание, что BaseList не владеет ее узлов. Когда вы выполняете push_back, список просто связывает объект с существующим списком, распределение не выполняется.

+0

'unique_ptr' противоречит требованиям OP. –

+0

@buttifulbuttefly обновил мой ответ, OP может просто игнорировать unique_ptr. –

+0

Но моя главная забота - это призыв к новому приращению цикла. Это то, что дорого стоит в моей программе, и я хотел бы знать, могу ли я назвать только один новый MyObject [10000] и скопировать результат в my_vector? – Silouane

1

Существует стандартная функция std::generate_n, что, кажется, в соответствии с вашими потребностями:

// Reserve space in vector to prevent unneeded reallocations 
my_vector.reserve(my_vector.capacity() + 10000); 
// Use back inserter to automatically call push_back each time 
// generate_n assigns value. Lambda will be called at each iteration 
// constructing new object. 
std::generate_n(std::back_inserter(my_vector), 10000, 
      []() { return new MyObject; });