Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 有没有可能写一个;“完成”;C++;使用零长度数组成员初始化?_C++_Stl_Flexible Array Member - Fatal编程技术网

C++ 有没有可能写一个;“完成”;C++;使用零长度数组成员初始化?

C++ 有没有可能写一个;“完成”;C++;使用零长度数组成员初始化?,c++,stl,flexible-array-member,C++,Stl,Flexible Array Member,我有一些数据类型,如果我使用普通的旧C,它将被实现为 typedef struct { ...many other members here... unsigned short _size; char _buf[0]; } my_data; 我想做的是,基本上把它变成一个类,并添加常用的操作符,如less、equality、copy构造函数、操作符赋值等等。正如您所想象的那样,我将在诸如std::map之类的关联容器中使用此类类作为其键 理想情况下

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

typedef struct {
    ...many other members here...
    unsigned short _size;
    char           _buf[0];
} my_data; 
我想做的是,基本上把它变成一个类,并添加常用的操作符,如less、equality、copy构造函数、操作符赋值等等。正如您所想象的那样,我将在诸如std::map之类的关联容器中使用此类类作为其键

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

对我来说,主要的问题是,在C语言中,我会有一个函数,给定缓冲区的大小,它会为它分配适当的内存大小。在C++中,这样的事情是不可能完成的。 我说得对吗?
干杯

您可以在C++中采用这种方式:

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

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

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

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


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

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


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

不,不可能。零长度数组不是合法的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];
};
请注意,默认构造函数、析构函数、复制构造函数和赋值运算符都是私有的,这大大限制了类的使用方式



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

不,这是不可能的。零长度数组不是合法的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];
};
请注意,默认构造函数、析构函数、复制构造函数和赋值运算符都是私有的,这大大限制了类的使用方式




1在实用术语中,它不是标准的,但它几乎在任何地方都能工作。

零数组长度数组成员在C++中是无效的,所以标题中的问题的答案是“否”。理论上-不,实际上-是的,绝对没有问题。也许你可以使用一些标准的容器代替?哦,顺便说一下,带有单个或双领先下划线的标识符由C和C++标准保留。@ Joachim Pileborg;带有单前导下划线的标识符仅在全局范围内保留(除非下划线后面的字符是大写字母)。所以, Buf很好。在C++中,零数组长度数组成员无效,所以标题中的问题的答案是“否”。理论上,不,实际上,是的,绝对没有问题。也许你可以使用一些标准的容器代替?哦,顺便说一下,带有单个或双领先下划线的标识符由C和C++标准保留。@ Joachim Pileborg;带有单前导下划线的标识符仅在全局范围内保留(除非下划线后面的字符是大写字母)。所以
\u buf
很好。谢谢。但是,如何在运行时动态地决定数据的分配大小?您必须先创建零大小的版本,然后再进行扩展。分配和初始化是C++中的两种不同的畜牲。在分配时间,
operator new
被指定为
sizeof(MyData)
,以便将其传递给
malloc
,但此时您无法告诉任何有关数据的信息。@Emanuele:
void*p=::operator new(sizeof(MyData)+您的buf长度);MyData*d=::new(p)MyData(),反正是这样的。这种方法的问题是不能使用像STL和/或智能指针之类的好功能。谢谢。但是,如何在运行时动态地决定数据的分配大小?您必须先创建零大小的版本,然后再进行扩展。分配和初始化是C++中的两种不同的畜牲。在分配时间,
operator new
被指定为
sizeof(MyData)
,以便将其传递给
malloc
,但此时您无法告诉任何有关数据的信息。@Emanuele:
void*p=::operator new(sizeof(MyData)+您的buf长度);MyData*d=::new(p)MyData(),无论如何都是这样。这种方法的问题是不能使用STL和/或智能指针之类的优秀功能。感谢您的确认。我将尝试使用自定义分配器解决此问题的部分原因,和/或我可能必须编写C容器来完成此操作(如您所建议的)。自定义分配器将是一个有趣的解决方案。我没有想到这一点,但实际上我不确定它的定义是什么。它将用于解决这个问题的部分原因,和/或我可以尝试使缓冲区在每个实例的指针之后启动,以便处于相同的位置