2

私は可変長データ構造、多次元イテレータを持っています:

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を参照)。この回答は、割り当てがデフォルトのパラメーターで実行されることを示唆しています。

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

どんなにエレガントでも、この解決策は役に立ちません: Default argument references parameter 'dim'. 素敵な解決策の提案はありますか?

4

4 に答える 4

2

残念ながら、これdimは実行時の値であるため、マクロを使用する以外にこれを行う方法はありません。

#define CREATE_ITERATOR(dim, sizes) \
    Iterator::init(dim, sizes, alloca(Iterator::alloc_size(dim)))
于 2012-07-20T12:01:17.323 に答える
1

テンプレート引数としてディメンション パラメータを指定できます。

于 2012-07-20T11:15:50.477 に答える
0

私の提案はあなたが探しているものではないかもしれませんが、 alloca 呼び出しを行う create|make_iterator 関数を持っていないのはなぜですか?

于 2012-07-20T11:50:03.817 に答える
0

alloca を使用することはまったくお勧めしません。dim 値が小さい場合は、クラス内の固定サイズのバッファーで十分です。dim が大きい場合、イテレーターで実行される他の操作の複雑さと比較して、ヒープ割り当てコストは無視できます (非常に大きな dim 値の場合、 alloca はスタック オーバーフローを引き起こす可能性があることに注意してください)。ディムのサイズに応じて、実行時に固定バッファーとヒープ割り当てのいずれかを選択できます。

したがって、std::string での小さな文字列の最適化と同様のアプローチをお勧めします。

おそらく、ある種の COW (copy on write http://en.wikipedia.org/wiki/Copy-on-write ) テクニックもイテレーターに役立つかもしれません。

この手法は alloca では使用できず、ヒープ割り当てでのみ使用できることに注意してください。さらに、イテレータが alloca を使用している場合、イテレータをコピーまたはコピーして初期化することはほとんど不可能です (少なくともますます醜いマクロがなければ)。

アロカは悪です:)

于 2012-07-20T15:05:42.630 に答える