C++ 可变大小班级的分配

C++ 可变大小班级的分配,c++,alloca,C++,Alloca,我有一个可变长度的数据结构,一个多维迭代器: 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) +

我有一个可变长度的数据结构,一个多维迭代器:

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
(参见例如)。这建议在默认参数中执行分配:

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

无论多么优雅,这个解决方案对我没有帮助:
默认参数引用参数“dim”
。有什么好的解决方案的建议吗?

您可以将维度参数作为模板参数。

我的建议可能不是您想要的,但是为什么不创建一个执行alloca调用的create | make_迭代器函数呢?

不幸的是,鉴于
dim
是一个运行时值,除了使用宏之外,没有其他方法可以做到这一点:

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

我不建议使用alloca。若dim值很小,那个么类中的一些固定大小的缓冲区就足够了。若dim很大,那个么和迭代器上执行的其他操作的复杂性相比,堆分配成本是可以忽略的(注意,对于非常大的dim值,alloca可能会导致堆栈溢出)。您可以在运行时选择固定缓冲区和堆分配,具体取决于dim大小

所以我推荐类似于std::string中的小字符串优化的方法

也许,某种COW(写时复制)技术对迭代器也很有用

注意,这种技术不能用于alloca,只能用于堆分配。此外,如果迭代器使用alloca(至少在没有越来越多难看的宏的情况下),复制或复制初始化迭代器几乎是不可能的


阿洛卡很邪恶:)

我一看到这个眼睛就痛。看起来像是无限递归(
bool done()const{return done();}
)与未定义行为的混合。@TadeuszKopec:hehe right,对不起:)我是说
done
。更正它。我仍然认为,
reinterpret\u cast
的解引用结果是未定义的行为。为什么是可变大小的对象?作为成员的good old
std::vector有什么问题?除了取消引用,您还会对
重新解释\u cast
的结果做什么?我不是一名语言律师,所以这可能是一种未定义的行为,但我想不出任何情况下这种转换可能会失败。关于我为什么不使用
std::vector
:称之为过早优化:)使用
reinterpret_cast
结果可以做的唯一一件事是将其转换回原始类型,前提是中间类型足够大,可以容纳转换值。任何其他用途都是UB。另外,
this+1
是UB,除非在数组中的对象中使用。不,我需要在运行时指定它。这不起作用,因为由
alloca
分配的内存会在函数返回时自动释放,如上所述。
#define CREATE_ITERATOR(dim, sizes) \
    Iterator::init(dim, sizes, alloca(Iterator::alloc_size(dim)))