Стандарт требует, чтобы вы были в состоянии создать массив типа структуры. Когда вы делаете это, массив должен быть смежным. Это означает, что какой бы размер ни был выделен для структуры, он должен быть таким, который позволяет вам создавать их массив. Чтобы гарантировать это, компилятор может выделить дополнительное пространство внутри структуры, но не может требовать дополнительного пространства между структурами.
Пространство для данных в vector
(обычно) выделяется с помощью ::operator new
(через класс Allocator), а ::operator new
требуется для выделения пространства, которое правильно выровнено для хранения любого типа.
Вы можете предоставить свой собственный Allocator и / или перегрузить ::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;
}