关于c ++:是否有可能有一个带有灵活数组成员的std :: vector结构?

Is it possible to have a std::vector of struct with a fexible array member?

我有一个具有灵活数组成员的结构,需要使用它。

1
2
3
4
5
struct Record
{
     uint32_t length;
     Data contents[];
};

我可以初始化它并通过这样的方式使用它:(它还可以与malloc或任何其他动态分配一起使用)

1
2
3
4
5
6
7
vector<Data> members;
vector<uint8_t> buffer;
Record myRecord;
buffer.resize(sizeof(Record) + members.size() * sizeof(Data));
myRecord = *(reinterpret_cast<Record*>(buffer.data());
myRecord.length = static_cast<uint32_t>(members.size());
// copy members to myRecord.contents

那就行了。但现在我需要有一个对成批记录进行操作的接口,我一直在尝试使用std::vector来实现这一点。然后问题开始出现,我猜这是因为std::vector在内存上连续排列所有元素,而且由于size of(record)不会考虑内容的大小(每个矢量元素只容纳4个字节,而不是4个字节+内容的大小*sizeof(data)),矢量元素实际上共享内存,然后每个元素开始覆盖上一个元素的内容。这有道理吗?

如果这确实是问题所在,我想知道是否有任何方法可以"强制"向量为每个元素分配一个特定的大小(而不是元素类型返回的size of)。这样我就可以确保每个向量元素都有足够的大小。如果不可能的话,还有其他的解决方案吗?也许另一个容器可以让我这样做?请记住,我确实需要使用它定义的结构(我希望只替换一个向量的整个内容,但不幸的是这是不可能的)


你的主要问题是:

1
myRecord = *(reinterpret_cast<Record*>(buffer.data());

这只是覆盖堆栈变量中的数据。这并没有改变myRecord的地址,使其突然指向buffer.data()。也就是说,当你稍后做myRecord.contents[...] = ...的时候,你会破坏堆栈。

你几乎可以肯定的是:

1
Record *myRecord = (reinterpret_cast<Record*>(buffer.data());

然后将有一个指向由buffer管理的内存的指针,该指针将有足够的存储空间用于myRecord->contents数组。

不能将EDOCX1[5]视为值类型。就C++的对象模型而言,它不是一个值类型。它不能像大多数C++类型那样被复制或移动。只能通过指向此处使用的特定分配的指针/引用来操作它。

也就是说,像这样使用vector来管理您的Record*的存储非常奇怪。最好使用unique_ptr,因为调整分配的大小是一个非常糟糕的主意。

1
std::unique_ptr<char[]> storage = new char[sizeof(Record) + (members.size() * sizeof(Data))];

这也会阻止系统初始化内存,因为您无论如何都要覆盖它。

I was wondering if there's any way to"force" the vector to allocate a specific size for each element (instead of whatever sizeof returns for the element's type).

不,vector管理同一类型的元素的连续数组。在C++中,同一类型的所有对象都具有相同的大小。