我有一个可变长度的数据结构,一个多维迭代器:
class Iterator
{
public:
static Iterator& init(int dim, int* sizes, void* mem)
{
return *(new (mem) Iterator(dim, sizes));
}
static size_t alloc_size(int dim)
{
return sizeof(Iterator) + sizeof(int) * 2 * dim;
}
void operator++()
{
// increment counters, update pos_ and done_
}
bool done() const { return done_; }
bool pos() const { return pos_; }
private:
Iterator(int dim, int* sizes) : dim_(dim), pos_(0), done_(false)
{
for (int i=0; i<dim_; ++i) size(i) = sizes[i];
for (int i=0; i<dim_; ++i) counter(i) = 0;
}
int dim_;
int pos_;
bool done_;
int size (int i) { return reinterpret_cast<int*>(this+1)[i]; }
int& counter(int i) { return reinterpret_cast<int*>(this+1)[dim_+i]; }
};
迭代器的维度在编译时是未知的,但可能很小,所以我使用alloca
为迭代器分配内存:
void* mem = alloca(Iterator::alloc_size(dim));
for (Iterator& i = Iterator::create(dim, sizes, mem); !i.done(); ++i)
{
// do something with i.pos()
}
是否有更优雅的方式为迭代器分配内存?我知道从函数返回后,它的堆栈被展开,因此必须在调用者的堆栈帧中使用alloca
(参见例如here)。这个answer表明分配是在默认参数中执行的:
static Iterator& init(int dim, int* sizes, void* mem = alloca(alloc_size(dim)));
不过很优雅,这个解决方案对我没有帮助:Default argument references parameter 'dim'
。有什么建议可以找到一个好的解决方案吗?
答案 0 :(得分:2)
不幸的是,鉴于dim
是一个运行时值,除了使用宏之外没有其他方法可以做到这一点:
#define CREATE_ITERATOR(dim, sizes) \
Iterator::init(dim, sizes, alloca(Iterator::alloc_size(dim)))
答案 1 :(得分:1)
您可以将dimension参数作为模板参数。
答案 2 :(得分:0)
我的建议可能不是您正在寻找的,但为什么没有创建alloca调用的create | make_iterator函数?
答案 3 :(得分:0)
我不建议使用alloca。如果昏暗值很小,那么类中的一些固定大小的缓冲区就足够了。如果dim很大,那么与迭代器上执行的其他操作的复杂性相比,堆分配成本可以忽略不计(请注意,对于非常大的dim值,alloca可能会导致堆栈溢出)。您可以在运行时选择固定缓冲区和堆分配,具体取决于昏暗大小。
所以我建议使用类似于std :: string中的小字符串优化的方法。
也许,某种COW(写入http://en.wikipedia.org/wiki/Copy-on-write)技术可能对你的迭代器也很有用。
请注意,此技术不能与alloca一起使用,只能使用堆分配。更重要的是,如果他们使用alloca(至少没有越来越多丑陋的宏),复制或复制初始化迭代器几乎是不可能的。