可变大小的类的分配(Allocation of variable-sized class)

2019-09-19 21:08发布

我具有可变长度数据结构,多维迭代:

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必须在调用者的堆栈帧被使用(例如参见这里 )。 这个回答表明,分配的默认参数来进行:

static Iterator& init(int dim, int* sizes, void* mem = alloca(alloc_size(dim)));

然而优雅,这种解决方案并不能帮助我: Default argument references parameter 'dim' 。 任何建议一个不错的解决方案吗?

Answer 1:

不幸的是,因为dim是运行时间值,没有什么比用宏来做到这一点其他:

#define CREATE_ITERATOR(dim, sizes) \
    Iterator::init(dim, sizes, alloca(Iterator::alloc_size(dim)))


Answer 2:

你可以有尺寸参数作为模板参数。



Answer 3:

我的建议可能不是你在找什么,但为什么没有创造| make_iterator函数,它的ALLOCA电话吗?



Answer 4:

我不会推荐给ALLOCA在所有使用。 如果调光值小,则一类内的一些固定大小的缓冲器就足够了。 如果暗淡较大,则堆分配成本会比较忽略对你的迭代执行其他操作的复杂性(注意,非常大的暗淡值ALLOCA可能会导致堆栈溢出)。 您可以固定缓冲区和堆分配之间的运行时间,这取决于暗淡大小来选择。

所以我建议更换类似的std :: string小串的优化方法。

也许,某种COW的(写时复制http://en.wikipedia.org/wiki/Copy-on-write )己技巧可能是你的迭代器也很有用。

请注意,这种技术不能与ALLOCA使用,只能用堆分配。 Morever,这几乎是不可能复制或复制,如果他们使用了alloca(至少在没有越来越难看macroses)初始化迭代器。

ALLOCA是邪恶的:)



文章来源: Allocation of variable-sized class
标签: c++ alloca