使用动态对象分配标准矢量内容

Allocating std vector content with dynamic objects

我有一个 std::vector< MyObject* > my_vector; 这不是空的,我想在其中分配和推送一定数量的 MyObject* 。 我知道要推送的对象数量。有没有比以下更好的方法 (optimized/faster):

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

就像为所有 MyObject 在一次 malloc 调用中分配,然后将结果 memcpy 到 my_vector。 有什么想法吗?

更新 我的问题是调用 new 10000 次。我希望能够分配一大块内存并将内存交换到 my_vector.

的末尾

你可以在 vector 中保留足够的 space,所以它只会分配一次内存。使用 std::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()));
}

更新:如果你不能使用(或不想)使用unique_ptr,只需在你的代码中添加reserve来预分配内存。

更新 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()));
}

这是一个简化的例子,它不是线程安全的,Pool 会在程序关闭时清除它的内存。它背后的想法类似于 flyweight gof pattern, see boost for example

更新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 时,列表只是将一个对象链接到现有列表,不执行任何分配。

有一个标准函数 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; });