是否可以使用带有灵活数组成员的std :: vector结构?

时间:2016-07-30 17:09:57

标签: c++ c++11 vector flexible-array-member

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

struct Record
{
     uint32_t length;
     Data contents[];
};

我能够初始化它并通过执行以下操作来使用它:(它也适用于malloc或任何其他动态分配)

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

这很好用。但是现在我需要有一个操作批量Record的接口,我一直在尝试使用std :: vector。然后问题开始出现,我猜测它是因为std :: vector在内存上连续排列所有元素,因为sizeof(Record)不会考虑内容的大小(每个vector元素只保存4个字节,而不是4个字节+ size_of_contents * sizeof(Data)),向量元素实际上是共享内存,然后每个元素开始覆盖前一个元素的内容。这有意义吗?

如果这确实是问题所在,我想知道是否有任何方法可以强迫&#34;强迫&#34;向量为每个元素分配一个特定的大小(而不是元素类型的任何sizeof返回值)。这样我就可以确保每个向量元素都有足够的大小。如果这不可行,是否有替代解决方案?也许是一个允许我这样做的不同容器?请记住,我需要使用它定义的结构(我很乐意只为一个向量替换整个东西但不幸的是,这是不可能的)< / p>

1 个答案:

答案 0 :(得分:2)

你的主要问题是:

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

这只是覆盖堆栈变量中的数据。这不会将myRecord的地址更改为突然指向buffer.data()。这意味着当您稍后执行myRecord.contents[...] = ...时,您将会破坏堆栈。

你几乎可以肯定的是:

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

然后你会得到一个指向由buffer管理的内存的指针,它将为myRecord->contents数组提供足够的存储空间。

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

话虽这么说,使用vector管理Record*这样的存储空间真的很奇怪。最好使用unique_ptr,因为重新调整分配将是一个非常糟糕的主意。

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

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

  

我想知道是否有任何方法可以强迫&#34;强迫&#34;向量为每个元素分配一个特定的大小(而不是元素类型的返回值)。

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