在我正在处理的代码库中,它目前有经常执行此操作的代码:
// In the header:
class Label
{
public:
void ParseText();
private:
Letter* m_myArray;
};
// In the CPP:
void ParseText()
{
delete[] m_myArray;
m_myArray = new Letter[string_length];
// ......
}
基本上每次标签中的字符串发生变化时,我们都会删除旧的字母对象集并重新创建它们。这些字母对象有些轻量级,但由于这种情况经常发生,我不能简单地使用 std::vector<Letter>
因为每个push_back()
会产生一个拷贝。我也想避免复制。
在这里使用 boost 池会有帮助吗?我可以想象这样做(这是伪代码,因为我还不确定如何使用 boost 池):
// In the header:
class Label
{
public:
void ParseText();
private:
std::vector<Letter*> m_myArray;
boost::object_pool m_pool;
};
// In the CPP:
void ParseText()
{
// Loop through each element in m_myArray and call pool::free
m_myArray.clear();
// Loop each letter and create a new Letter object in the container
for( ... ) {
m_myArray.push_back(m_pool.malloc()); // Not sure how to handle constructor params
}
// ......
}
这将避免复制并避免如此频繁地进行分配。但是,我降低了代码的可维护性,因为在 vector 中添加/删除项目涉及太多样板。
我考虑过将 boost::ptr_vector 与自定义删除器一起使用,但不确定这是否有帮助。它有助于清理,但我仍然必须调用 pool::malloc()
每次我做一个 push_back。
将自定义分配器与 std::vector 一起使用似乎也没有意义,因为它无论如何都是预先分配的,并且不会缩小大小。
谁能帮我找出解决这个问题的“最佳”解决方案?
最佳答案
我认为内存池在某些情况下会有所不同。自 boost::object_pool<>
没有提供分配对象数组的方法,所以我会使用 boost::pool<>
这实际上是boost::object_pool<>
的底层内存池.
#include <cstdio>
#include <ctime>
#include "boost/pool/pool.hpp"
struct Letter{
float a, b, c;
int *p;
};
class Label
{
public:
Label() : m_myArray(NULL), string_length(1), last_size(0){}
void set_size(size_t n)
{
last_size = string_length; // use last_size to store the number of last allocation, just for test.
string_length = n;
}
void ParseText()
{
delete[] m_myArray;
m_myArray = new Letter[string_length];
}
void ParseText_pool();
private:
Letter* m_myArray;
size_t string_length;
size_t last_size; //boost::pool<>::ordered_free need the size
};
boost::pool<> p(sizeof(Letter));
void Label::ParseText_pool()
{
if(m_myArray)
p.ordered_free(m_myArray, last_size); // ordered_free need the right size
m_myArray = (Letter*)p.ordered_malloc(string_length); // if you need call the ctor, use placement new.
}
int main()
{
Label l;
float startTime = (float)clock()/CLOCKS_PER_SEC;
for(int i = 1; i < 1000000; ++i)
{
l.set_size(i%100 + 1);
l.ParseText();
}
float endTime = (float)clock()/CLOCKS_PER_SEC;
printf("without pool, time: %f\n", endTime - startTime);
Label l2;
startTime = (float)clock()/CLOCKS_PER_SEC;
for(int i = 1; i < 1000000; ++i)
{
l.set_size(i%100 + 1);
l2.ParseText_pool();
}
endTime = (float)clock()/CLOCKS_PER_SEC;
printf("with pool, time: %f\n", endTime - startTime);
};
在我的机器上运行 coliru ,说明分配越频繁,使用内存池的优势越大。
关于c++ - 使用 boost.pool 而不是 'new' 作为对象容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23199257/