我有一个带有灵活数组成员的结构,我需要使用它。
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>
答案 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 ++中,所有相同类型的对象都具有相同的大小。