使用std :: vector <char>作为异构记录的存储是否安全?

时间:2018-06-12 23:14:42

标签: c++ language-lawyer

我需要处理由一系列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很好地处理内存管理。 但它有效吗?

1 个答案:

答案 0 :(得分:1)

由于违反严格别名和对齐行为,根据标准,您提议的选项都不正确。

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