C++ struct alignment和STL向量

Nat*_*ate 7 c++ stl

我有一个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);
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,但我认为它只能起作用,因为数据结构大小恰好可以被编译器的结构对齐填充整除.我怀疑它会破坏其他编译器或平台.

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

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

Jer*_*fin 4

该标准要求您能够创建结构类型的数组。当您这样做时,数组需要是连续的。这意味着,无论为结构分配多少大小,它都必须允许您创建它们的数组。为了确保这一点,编译器可以在结构内部分配额外的空间,但不能在结构之间要求任何额外的空间。

a 中数据的空间(通常)是通过(通过 Allocator 类)vector分配的,并且需要分配正确对齐的空间来存储任何类型。::operator new::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;
}
Run Code Online (Sandbox Code Playgroud)