我有一个672字节长的旧数据结构。这些结构按顺序存储在文件中,我需要读入它们。

虽然我可以一一阅读它们,但是这样做很不错:

// I know in advance how many structs to read in
vector<MyStruct> bunchOfStructs;
bunchOfStructs.resize(numberOfStructs);

ifstream ifs;
ifs.open("file.dat");
if (ifs) {
    ifs.read(&bunchOfStructs[0], sizeof(MyStruct) * numberOfStructs);
}

这行得通,但我认为这仅行得通,因为数据结构大小恰好可以被编译器的结构对齐填充均匀地整除。我怀疑它将在另一个编译器或平台上中断。

另一种方法是使用for循环一次读取每个结构。

问题->我什么时候需要关注数据对齐? vector 中动态分配的内存使用填充还是STL保证元素是连续的?

最佳答案

该标准要求您能够创建结构类型的数组。这样做时,数组必须是连续的。这意味着,无论为该结构分配了多少大小,它都必须是允许您创建它们的数组的大小。为了确保这一点,编译器可以在结构内部分配额外的空间,但不能在结构之间要求任何额外的空间。
vector中的数据空间(通常)是通过::operator new分配的(通过Allocator类),并且::operator new是必需的,以分配适当对齐的空间来存储任何类型。

您可以提供自己的分配器和/或重载::operator new-但是,如果这样做,仍然需要您的版本满足相同的要求,因此在这方面不会有任何更改。

换句话说,只要文件中的数据以与尝试读回该文件的方式基本相同的方式,就可以正常工作。如果该文件是在另一台计算机或其他编译器上创建的(甚至是带有不同标志的同一个编译器),都有很多潜在的问题-您可能会在字节序,结构填充等方面有所不同。

编辑:鉴于您不知道结构是否已经以编译器期望的格式写出,您不仅需要一次读取一个结构-您确实需要读取结构中的项目一段时间,然后将它们分别放入临时的struct中,最后将填充的struct添加到您的收藏夹中。

幸运的是,您可以重载operator>>来自动执行大部分操作。例如,它不会提高速度,但是可以使代码更干净:

struct whatever {
    int x, y, z;
    char stuff[672-3*sizeof(int)];

    friend std::istream &operator>>(std::istream &is, whatever &w) {
       is >> w.x >> w.y >> w.z;
       return is.read(w.stuff, sizeof(w.stuff);
    }
};

int main(int argc, char **argv) {
    std::vector<whatever> data;

    assert(argc>1);

    std::ifstream infile(argv[1]);

    std::copy(std::istream_iterator<whatever>(infile),
              std::istream_iterator<whatever>(),
              std::back_inserter(data));
    return 0;
}

关于c++ - C++结构对齐和STL vector ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2307933/

10-11 22:41
查看更多