десериализация из std :: fstream - PullRequest
0 голосов
/ 02 ноября 2011

Есть ли что-то особенно плохое или наивное в чтении сериализованных данных (известного формата + порядковый номер) из файла, используя что-то вроде этого?Я не беспокоюсь о переносимости, и реально он будет использоваться только мной.Я знаю, что одной проблемой будет попытка извлечь неупакованную структуру POD, хотя я всегда могу определить отдельный operator> для каждой такой структуры.

template<typename T> inline std::fstream& operator> (std::fstream& fs, T& i) {
    static_assert(std::is_pod<T>::value, "Not POD");
    fs.read(reinterpret_cast<char*>(&i), sizeof i);
    return fs;
}
template<typename T> inline std::fstream& operator> (std::fstream& fs, std::vector<T>& v) {
    static_assert(std::is_pod<T>::value, "Not POD");
    fs.read(reinterpret_cast<char*>(&v[0]), sizeof(T) * v.size());
    return fs;
}
template<typename T> inline std::fstream& operator> (std::fstream& fs, std::vector<std::vector<T>>& v) {
    for (auto& i : v)
        fs > i;
    return fs;
}
inline std::fstream& operator> (std::fstream& fs, std::string& s) {     
    fs.read(reinterpret_cast<char*>(&s[0]), s.size());
    return fs;
}

std::fstream f("file", std::ifstream::in | std::ifstream::out | std::ifstream::binary);
int i;
char j;
std::vector<std::vector<char>> vec(5, std::vector<char>(8));

f > i > j > vec;

1 Ответ

2 голосов
/ 02 ноября 2011

Я не уверен, что вы спрашиваете.Код, который вы публикуете, не читает сериализованные данные "известного формата или порядкового номера".Он копирует байты из файла в любое место, что может привести к неопределенному поведению, и очень маловероятно, что оно приведет к правильным значениям, если по какой-то странной случайности «известный формат» точно соответствует тому, который используется внутри вашей машины.Во многих случаях, на самом деле, это может привести к аварийному завершению программы;подумайте о том, что может произойти, если структура, которую вы пытаетесь прочитать, содержит указатель, например.

Я мог бы добавить, что перегрузка '>' для этого ужасного злоупотребления перегрузкой;если вы хотите прочитать специальный формат, логичный способ сделать это - определить соответствующий класс (например, ixdrstream) и перегрузить его >>.(ixdrstream вероятно будет производным от std::basic_ios<char>, конечно, и почти наверняка будет использовать стандарт streambuf для фактического ввода.)

И, конечно, вы никогда не перегружаетесь на std::fstream, а скореена std::istream (или std::ostream для вывода).(FWIW, я не думаю, что когда-либо использовал std::fstream. Идиома потока действительно не поддерживает смешивание чтения и записи элегантно.)

...