Вы на самом деле не хотите copy
метод вообще. Вам просто нужен конструктор копирования и оператор присваивания. Я предполагаю, что ваша строка изначально выглядела так:
g = myServer->getAgent()->getGrid();
И так как это не сработало, вы добавили метод копирования. Но в настоящее время исправление только одного метода копирования не решит проблему, так как вам также понадобятся конструктор копирования и оператор присваивания, или ваша тяжелая работа по исправлению метода копирования может быть уничтожена.
Во-первых, краткое объяснение того, что происходит и почему программа не работает:
- Звоните
copy
- Это вводит ваш метод копирования, который создает
Grid
в стеке.
- Он устанавливает членов
Grid
, но мы подозреваем, что это мелкая копия.
- Возвращает метод copy, который вызывает конструктор копирования
Grid
. *
- Конструктор копирования по умолчанию делает поверхностную копию.
- Деструктор
Grid
на основе стека срабатывает, удаляя содержимое map
.
- Метод копирования теперь вернулся, предоставив временную
Grid
, но такую, которая указывает на удаленную память.
- Теперь временный объект
Grid
назначен на g
. Это вызывает оператор присваивания Grid
. *
- Оператор присваивания по умолчанию выполняет поверхностное копирование, как это делал конструктор копирования по умолчанию.
- В конце строки временный объект уничтожается, где он пытается удалить содержимое
map
, которое уже было удалено. стрела.
- Когда
g
выходит из области видимости, его деструктор снова попытается удалить содержимое map
.
Как видите, есть 3 места, где происходит мелкое копирование - все должно быть исправлено, иначе это все равно не получится.
Как это исправить
- Избавьтесь от метода копирования - он все равно не дает никакого значения.
- Исправьте
setMap
и setFilename
, чтобы сделать глубокую копию.
- Создать оператор присваивания. Это должно глубоко копировать содержимое другой сетки.
- Создайте конструктор копирования, как оператор присваивания.
Вот как может выглядеть оператор присваивания (при условии, что все заданные методы выполняют глубокое копирование):
Grid& operator= (const Grid& g) {
setFilename(f_name);
setNumOfRows(num_rows);
setNumOfCols(num_cols);
setMap(map);
return *this;
}
Существуют методы написания конструктора копирования, а затем заставить оператор присваивания использовать конструктор копирования. Это хорошая техника (меньше дублированного кода), но у меня нет удобной ссылки. Когда я найду это, я свяжу это здесь.
Наконец, я отметил несколько строк в своем объяснении (*). Компиляторы могут выполнять оптимизацию возвращаемых значений (RVO) и именованные RVO. С этими оптимизациями он фактически не будет создавать объект Grid
в стеке в пределах copy
, а затем копировать-конструкцию для возвращаемого значения - он просто создаст временный объект для результата copy
, а затем метод copy
будет использовать его вместо своего собственного Grid
объекта, основанного на стеке. Таким образом, при достаточном количестве оптимизаций компилятора ваш код может преодолеть эту точку и позже потерпеть крах. Очевидно, это бесполезно, так что это, скорее, к сведению.