2012-07-20 100 views
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)。這answer表明,分配在默認參數下進行:

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

然而優雅,這種解決方案並不能幫助我:Default argument references parameter 'dim'。任何建議一個很好的解決方案?

+0

您可以使用宏。 – 2012-07-20 11:30:25

+0

我的眼睛在看着這個傷害。看起來像無限遞歸的混合('bool done()const {return done();}')具有未定義的行爲。 – 2012-07-20 11:41:00

+0

@TadeuszKopec:呵呵吧,對不起:)我的意思是'done_'當然。糾正它。 – marton78 2012-07-20 12:27:10

回答

2

不幸的是,由於dim是運行時間值,沒有什麼比用宏來做到這一點其他:

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

您可以將維度參數作爲模板參數。

+0

不,我需要它在運行時指定。 – marton78 2012-07-20 12:24:23

0

我的建議可能不是你正在尋找的,但爲什麼不具有執行alloca調用的create | make_iterator函數?

+1

這是行不通的,因爲一旦函數返回,'alloca'分配的內存就會自動釋放,如上所述。 – marton78 2012-07-20 12:25:24

0

我不會推薦給ALLOCA在所有使用。如果dim值很小,那麼類中的一些固定大小的緩衝區就足夠了。如果dim很大,那麼與你的迭代器上執行的其他操作的複雜度相比,堆分配成本是可以忽略的(請注意,對於非常大的dim值,alloca可能導致堆棧溢出)。您可以在運行時選擇固定緩衝區和堆分配,具體取決於調光大小。

所以我建議類似於std :: string中的小字符串優化的方法。

也許,某種COW(複製寫http://en.wikipedia.org/wiki/Copy-on-write)techique也可能對您的迭代器有用。

請注意,該技術不能與alloca一起使用,只能與堆分配一起使用。此外,如果他們使用alloca(至少沒有更多更醜陋的宏),複製或複製初始化迭代器幾乎是不可能的。

Alloca is evil :)