2012-08-10 51 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]; 
}; 

需要注意的是默认的构造函数,析构函数,拷贝构造函数和赋值操作符都是私有的,这极大地限制了类如何都可以使用。


实际上 - 它不符合标准的,但它的工作几乎无处不在。

相关问题