2012-08-10 46 views
1

我有,如果我使用普通的舊的C,將實現爲是否可以使用零長度數組成員編寫「完整」C++類?

typedef struct { 
    ...many other members here... 
    unsigned short _size; 
    char   _buf[0]; 
} my_data; 

我想怎麼辦,是一些數據類型基本上做出一個並添加通常的運營商如平等拷貝構造函數運營商分配,等等。正如你可以想象的那樣,我會在關聯容器中使用,例如std :: map,因爲它的。我需要緩衝區理想地位於對象本身的相同級別,否則當我必須比較它們中的兩個(緩衝區)時,我會讓CPU取指針並將其加載到內存中;我不想使用std :: vector,因爲分配的內存不會與其餘數據成員連續

對我來說主要問題是,在C我會有一個函數,考慮到緩衝區的大小會爲它分配適當的內存大小。在C++這樣的事情是不能做到的。

我對不對? 乾杯

+4

零數組長度數組成員在C++中無效,因此標題中問題的答案爲「否」。 – 2012-08-10 07:29:51

+0

理論上 - 沒有。實際上 - 是的,這絕對沒有問題 – valdo 2012-08-10 07:30:39

+0

'_buf'的目的是什麼?也許你可以使用一些標準容器來代替? – 2012-08-10 07:32:25

回答

1

這是完全不可能的。您的對象實際上具有可變大小,但std::map將始終將其視爲固定大小,並且無法執行復制或移動。你需要一箇舊的C風格容器來使用這種黑客。

編輯:自定義分配器。有趣的解決方案,我沒有想到這一點。我不知道你是否能做到這一點,但值得研究。

+0

感謝您的確認。我將嘗試使用自定義分配器來解決此問題的部分原因_and/or_我可能必須編寫_C_容器才能這樣做(如您所建議的那樣)。 – Emanuele 2012-08-10 07:55:49

+0

自定義分配器將是一個有趣的解決方案。我沒有想到這一點,*但我*不確定它將如何定義。 – Puppy 2012-08-10 07:57:06

+0

它將被用來解決這個問題的原因的一部分,和/或我可以**嘗試**使緩衝區在每個實例的指針之後開始_right,以便在同一個CPU _CACHELINE_上。 – Emanuele 2012-08-10 08:04:35

0

可以接近這種方式在C++:

struct MyData { 
    unsigned short size_; 
    char * buf() { return reinterpret_cast<char *>(&size_ + 1); } 
    //... 
}; 

你可能會想重載new操作人員使用malloc,並delete使用free,這樣就可以增加你的數據結構按需要與realloc

正如DeadMG指出的那樣,這個容器不能很容易地與STL容器一起使用。一種方法是在容器中使用指向MyData的指針。另一個將是一個定製的智能指針包裝類MyData

編輯:這是一個黑客,其中MyData作爲一種智能指針,但智力是由vector管理。

struct MyData { 
    struct State { 
     unsigned short size_; 
     //... 
    }; 
    std::vector<State> data_; 
    MyData() {}; 
    MyData (unsigned short size) 
     : data_(1 + size/sizeof(State) + !!size%sizeof(State)) { 
     data_[0].size_ = size; 
    } 
    unsigned short size() const { return data_[0].size_; } 
    //... 
    char * buf() { return reinterpret_cast<char *>(&data_[1]); } 
}; 
+0

謝謝。但是如何在運行時動態決定_Data_的_allocated_大小? – Emanuele 2012-08-10 07:48:20

+0

您必須首先創建零大小版本,然後進行增大。 – jxh 2012-08-10 07:50:27

+1

C++中的分配和初始化是兩種不同的野獸。在分配的時候'operator new'被賦予'sizeof(MyData)'以便將它傳遞給'malloc',但此時你不能告訴任何有關數據的事情。 – 2012-08-10 07:50:33

0

不,這是不可能的。零長度數組不是合法的C++。

可以做長度爲1的數組非常類似的東西,但你仍然要管理創建實例自己,所以沒有拷貝構造函數和無存儲std::map的對象。

也許是這樣的:

class my_data { 
public: 
    static my_data* create(int size) { 
    void* memory = malloc(sizeof(_size) + size); 
    return new(memory) my_data(size); 
    } 

    static void destroy(my_data* ptr) { 
    ptr->~my_data(); 
    free(ptr); 
    } 

private: 
    //disable construction and destruction except by static methods above 
    explicit my_data(int size) : _size(size) {} 
    ~my_data(){} 

    //disable copying 
    my_data(const my_data&); 
    my_data& operator=(const my_data&); 

    unsigned short _size; 
    char   _buf[1]; 
}; 

需要注意的是默認的構造函數,析構函數,拷貝構造函數和賦值操作符都是私有的,這極大地限制了類如何都可以使用。


實際上 - 它不符合標準的,但它的工作幾乎無處不在。

相關問題