1

我有一些数据类型,如果我使用普通的旧 C,将被实现为

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

我想做的,基本上是把它变成一个,并添加常用的运算符,如lessequalcopy constructoroperator assignment等。正如您可以想象的那样,我将在std::map等关联容器中使用此类作为其key

我需要缓冲区在理想情况下与对象本身处于同一级别,否则当我必须比较其中两个(缓冲区)时,我会让 CPU 获取指针并将其加载到内存中;我不想使用std::vector因为分配的内存不会与其余的数据成员连续。

对我来说主要问题是在C 语言中我会有一个函数,给定缓冲区的大小,它会为其分配适当的内存大小。在C++中,这样的事情是做不到的。

我对吗?干杯

4

3 回答 3

1

这是完全不可能的。您的对象实际上是可变大小的,但std::map将始终将其视为固定大小,并且无法实现复制或移动。你需要一个旧的 C 风格的容器来使用这样的 hack。

编辑:自定义分配器。有趣的解决方案,我没有想到这一点。我不知道你是否可以让它工作,但它值得研究。

于 2012-08-10T07:48:21.527 回答
0

您可以在 C++ 中以这种方式处理它:

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

您可能希望重载new运算符以使用mallocdelete使用free,以便您可以根据需要扩展数据结构realloc

正如 DeadMG 所指出的,这不能STL很容易地与容器一起使用。一种方法是MyData在容器中使用指针。另一个是用于MyData.

编辑:这是一个 hack,它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]); }
};
于 2012-08-10T07:46:14.257 回答
0

不,这是不可能的。零长度数组不是合法的 C++。

您可以1使用长度为 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];
};

注意默认构造函数、析构函数、复制构造函数和赋值运算符都是私有的,这极大地限制了类的使用方式。


1实际上 - 它不符合标准,但几乎可以在任何地方使用。

于 2012-08-10T07:55:21.840 回答