我需要处理由一系列POD元素组成的记录。
在处理一系列这些记录之前,会在运行时找到这些元素的类型。理想情况下,记录的存储将连续地容纳元素,以便可以直接填充存储或通过系统IO调用输出存储。

给出以下简化的示例代码:

template<typename T>
struct ElementAccessor {
    ElementAccessor(int offset)
    :
        _offset(offset)
    {}

    T &operator () (void * data)
    {
        return reinterpret_cast<T &>(
           *reinterpret_cast<char *>(data) + _offset);
    }
    int _offset;
};

ElementAccessor<float> fEl(0);
ElementAccessor<int> iEl(sizeof(float));

我正在寻找一种有效且方便的方式来存储记录吗?

我考虑了以下方法:

vector<int>

使用vector<int>似乎很方便:
std::vector<int> intData(2);
iEl(intData.data()) = 42;
fEl(intData.data()) = 12.4f; //< Uh-oh,  undefined behaviour, maybe zero initialization could be reordered after this point!

但会违反严格混叠规则。

Raw allocated memory

我相信以下是有效的代码,但是由于内存管理是手动的,因此不方便:
void *voidData(operator new(2 * sizeof(int)));
iEl(voidData) = 42;
fEl(voidData) = 12.4f;
...
operator delete(voidData);

std::vector<char>

如何使用std::vector<char>:
std::vector<char> charData(2 * sizeof(int));
iEl(charData.data()) = 42;
fEl(charData.data()) = 12.4f;

便利的是std::vector很好地处理了内存管理。
但这有效吗?

最佳答案

根据标准,由于违反严格的混叠和对齐方式,因此您提出的所有选项都不正确。

您可以做的是在缓冲区的任意偏移量与您选择的类型之间的memcpy。但是没有对数据“就地”进行操作。

10-04 12:08
查看更多