使用动态对象分配标准矢量内容
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; });
我有一个
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; });