Сохранить пользовательский тип данных в файл в C ++ - PullRequest
0 голосов
/ 23 ноября 2018

У меня есть такой класс:

struct SomeClass{

    SomeClass(){}

    SomeClass(const SomeClass& rhs):
    _m1(rhs._m1),
    _m2(rhs._m2),
    _m3(rhs._m3),
    _m4(rhs._m4){}

    SomeClass& operator=(const SomeClass& rhs){
    // same as above
    return *this;
    }

    int _m1;
    std::vector<int> _m2;
    std::vector<int> _m3;
    int _m4;
};

В какой-то момент в моей программе я хочу сохранить данные, хранящиеся в объекте SomeClass, для последующего использования:

    SomeClass someObj = arr->getBest(); // arr is a pointer to AnotherClass,
                                        // in which different SomeClass
                                        // objects are initialized and then
                                        // involved in various 
                                        // computations in AnotherClass, 
                                        // finally the best one SomeClass 
                                        // object will be save here
    fwrite(&someObj, sizeof(SomeClass), 1, saveFile);

После сохранения файла в saveFile, я пытаюсь прочитать его и получаю ошибку:

    SomeClass readingSomeObj;
    fread(&readingSomeObj, sizeof(SomeClass), 1, savedFile));

Жалобы компилятора "Расположение чтения нарушения доступа 0x ...".Наблюдая за местными жителями в VS, я вижу, что два других поля readingSomeObj, а именно _m1 и _m4 имеют значения в них, но не _m2 и _m3, в VS это говорит "неспособно прочитать память».vs error prompt

Кроме того, проблема связана с SomeClass, а именно с этой строкой _m2(rhs._m2),.

Но когда я сохранял someObj встрока fwrite(&someObj, sizeof(SomeClass), 1, saveFile); Я видел, что два члена _m2 и _m3 из someObj имеют значения (наведите указатель мыши на &someObj).

Я не могу понять, что происходит не так,Я предполагаю, что проблема с конструкторами SomeClass, но все же, как новичок в C ++, я не знаю, как это исправить.В других частях моей программы я использовал пустой конструктор SomeClass для инициализации члена AnotherClass.Но все работает нормально, за исключением этой части сохранения / чтения.Я ищу вашу щедрую помощь и спасибо миллион!

Ответы [ 2 ]

0 голосов
/ 23 ноября 2018

Вы сделали массу предположений о типе данных, которые не сохраняются.Наиболее вопиющим является то, что все его байты хранятся в «строке» в памяти, все рядом друг с другом, что является единственным способом, когда блок-копирование и чтение может работать когда-либо.

Это можетдержится для POD (выравнивание по модулю и порядку байтов), но оно не будет работать для сложных типов данных, таких как vector, которые указывают на «реальные» данные, фактически хранящиеся в другом месте (посредством динамического выделения).

Ваши десериализованные векторы состоят изв основном только из значений указателей, которые давно недействительны.

Ваша процедура сериализации должна быть более умной, чем эта.В конечном счете, нет единого способа сделать это.Вы можете определить свой собственный формат или использовать какое-либо готовое решение для сериализации, которое уже имеет формат, поддерживающий стандартные контейнеры.

Для некоторых идей вы можете использовать Google "Сериализация классов C ++".

0 голосов
/ 23 ноября 2018

Вы не можете сериализовать векторы как это.Им выделена память, поэтому сделайте что-то вроде:

  • Сохраните ваши целые числа в файле
  • Сохраните размер первого вектора
  • Сохраните содержимое вашего первогоvector
  • Сделайте то же самое для второго вектора

Затем, когда вы читаете ваш файл:

  • Читайте два целых числа
  • Читатьваш первый векторный размер, выделите вектор
  • Считайте значения для вашего первого вектора
  • Сделайте то же самое для второго вектора.

Вы также можете использовать сериализациютакая библиотека, как Boost.Serialization, которая более надежно справляется с этой задачей.

...