我有一个Visual Studio 2008 C ++程序,我正在使用内存池的地址填充std::list
。
我有一个使用std::generate
工作的实现,并且它不错,但是对于大型小分配块池,它可能会有点慢。
/// fill the allocation list with the memory addresses of each block
struct fill
{
fill( void* start, ulong alloc )
: start_( start ),
alloc_( alloc ),
count_( 0 )
{
};
void* operator()()
{
return ( void* )( ( ulong ) start_ + ( count_++ ) * alloc_ );
}
/// starting address
void* start_;
/// size of the blocks
ulong alloc_;
/// internal counter
int count_;
}; // struct fill
ulong begin = 0; // beginning address
ulong max_size = 0x1000; // maximum memory pool size (4KB)
ulong block_size = 0x20; // size of each memory block (32B)
std::list< void* > memory;
memory.resize( max_size / block_size ); // 128 memory blocks
std::generate( memory.begin(), memory.end(), fill( begin, block_size ) );
我只是想知道是否有人有更快或更有效的方法来填充链表。
谢谢, PaulH
答案 0 :(得分:3)
您的代码会在列表中传递两次而不是一次。
因此,定义一个返回地址的迭代器可能会有所帮助,所以一切都在一次传递中完成:
struct blocks {
void *current;
size_t increment;
blocks(void* start, size_t size = 0) : current(start), increment(size) {}
bool operator==(const blocks &rhs) const { return current == rhs.current; }
bool operator!=(const blocks &rhs) const { return current != rhs.current; }
void *operator*() const { return current; }
blocks &operator++() {
current = (void*)( (char*)current + increment );
return *this;
}
};
std::list<void*> memory(blocks(begin, block_size), blocks(max_size));
(代码未经过测试,我遗漏了一些你需要的东西才能成为一个合适的迭代器 - 如果没有别的东西需要标记,并且通常会欢迎后期增量。)
目前它只是一个ForwardIterator(或者,如果被标记的话)。你可以很容易地使它成为一个RandomAccessIterator,但你必须给结束迭代器正确的大小。如果您使用char(*)[block_size]
的容器而不是void*
的容器,那么我认为您可以使用boost::counting_iterator<char(*)[block_size]>
来填充它。
但从根本上说,std::list
在这方面适度缓慢。除非您打算在中间插入/删除(这对于内存池空闲列表来说似乎是不必要的 - 如果所有块都是相同的大小,您应该能够始终在末尾添加和删除),您可能会做得更好使用矢量或双端队列,或者至少使用侵入式链接列表。