Ошибка утверждения при передаче объекта по значению — это мой конструктор копирования?

каждый!

Я только что закончил писать 2-D лабиринт (Class — это ADT под названием «Maze» — как оригинально), который использует динамическое распределение памяти. Я передаю Лабиринт методу другого класса под названием «MazeSolver», в котором для решения лабиринта используются рекурсия и возвратный путь. Хорошей новостью является то, что мой код прекрасно компилируется, когда я передаю объект по ссылке. Новости, которые я не знаю, хорошо это или плохо, заключаются в том, что я получаю ошибку подтверждения, если пытаюсь передать Лабиринт в MazeSolver по значению.

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

Лабиринт состоит из квадратов. Каждый квадрат представлен структурой с именем SquareData.

      struct SquareData
{
//data fields for the struct (NO POINTERS)
}

Я решил представить весь лабиринт с помощью вектора указателей SquareData (этот вектор находится в закрытом разделе класса «Лабиринт»).

vector<SquareData*> squares;

Реализация моего деструктора выглядит следующим образом (этот последний вызов, ссылающийся на класс Player, просто устраняет висячий указатель, который я объявил как статическую переменную для этого класса, который я указал на лабиринт. Я не думаю, что это важно, учитывая вопрос , но я все-таки новичок в C ++, и один из вас может подумать, что это так, поэтому я включил его для «хммм»):

// clears maze of its contents
void Maze::clear() {
int totalSquares = squares.size();
for (int loopVar = 0; loopVar < totalSquares; loopVar++)
{
delete squares[loopVar]; // deallocate memory by deleting the square structure
squares[loopVar] = nullptr; // eliminate dangling pointer
} // vector takes care of itself
} // end clear

Maze::~Maze(){
//clear the maze of contents (vector is full of pointers whose memory is on the heap)
clear();
//vector safe to deallocate itself now
Player::setMaze(nullptr); // remove the pointer from player
}

Я объявил конструктор копирования в заголовке следующим образом:

/** Copy Constructor */
Maze(const Maze& myMaze);

с попыткой реализации:

/** copy constructor */
Maze::Maze(const Maze& myMaze){
/** Initialize Constants */
mazeLength = myMaze.mazeLength;
mazeWidth = myMaze.mazeWidth;
exitRow = myMaze.exitRow;
exitCol = myMaze.exitCol;
entRow = myMaze.entRow;
entCol = myMaze.entCol;
/** copy the vector of pointers*/
for (int loopVar = 0; loopVar < myMaze.squares.size(); loopVar++)
{
squares.push_back(myMaze.squares[loopVar]);
}
} // end copy constructor

Вот как я пытался понять, что делает проблема:

Я написал эту векторную функцию для моего класса лабиринта.

void Maze::vectorDisplay() const {
for (int loopVar = 0; loopVar < squares.size(); loopVar++)
{
cout << "Vector Index: " << loopVar << endl;
cout << "Pointer: " << squares[loopVar] << endl;
cout << "Row: " << squares[loopVar]->Row << endl;
cout << "Col: " << squares[loopVar]->Col << endl;
cout << "State: " << squares[loopVar]->State << endl;
}
} //end vectorDisplay

И обнаружил, что вектор отображается правильно при выполнении следующих действий в драйвере:

    Maze myMazeObject(// parameters);
myMazeObject.vectorDisplay();

и будет производить продукцию без нареканий.

Но теперь, если я попытаюсь использовать такой код при передаче по значению:

Maze myMazeObject(// parameters);
MazeSolver myMazeSolver;
myMazeSolver.someMazeSolverMethod(myMazeObject);

где someMazeSolverMethod имеет строку myMazeObject.vectorDisplay();Я получаю ошибку утверждения, когда печатается последний элемент вектора.

Я хочу сказать, что это моя ошибка, и мой конструктор копирования — это p.o.s. Если есть понимание, пожалуйста, дайте мне знать, как это исправить и что я могу сделать в будущем!

Спасибо, что нашли время, чтобы прочитать и даже больше, чтобы ответить, если вы решите!

-J

0

Решение

Использование

    squares.push_back(myMaze.squares[loopVar]);

в конструкторе копирования это приведет к проблемам в нисходящем направлении. squares были объекты, а не указатели.

Теперь есть два объекта, удерживающие указатели. Обе попытаются позвонить delete по тому же указателю, что легко приводит к неопределенному поведению.

Вы можете решить проблему следующим образом:

  1. Используя vector объекты вместо vector указателей, или
  2. Создание новых объектов из кучи и добавление их в новый объект.

    squares.push_back(new SquareData(*myMaze.squares[loopVar]));
    
0

Другие решения

Это твоя проблема.

    squares.push_back(myMaze.squares[loopVar]);

В основном каждый лабиринт имеет вектор, полный одинаковых указателей. Когда одна копия лабиринта выходит из области видимости, он удалит все указатели. Таким образом, другой лабиринт теперь имеет набор недействительных указателей.

Пара решений.

  1. Не используйте указатели.

Если только ты не SquareData Полиморфный, кажется, нет смысла сохранять указатели.

 std::vector<SquareData> squares;
  1. Если вы хотите, чтобы каждая копия лабиринта ссылалась на одни и те же квадраты.

Затем используйте общий указатель. Это будет вести подсчет количества ссылок на каждый SquareData и, таким образом, удаляйте их только тогда, когда они действительно выходят за рамки.

 std::vector<std::shared_ptr<SquareData>> squares;
  1. Наименее привлекательный (и, вероятно, не нужен).

Измените код, чтобы фактически скопировать содержимое указателя в новый объект.

squares.push_back(new SquareData(myMaze.squares[loopVar]));
1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector