Проблемы с памятью массива 2D-объектов C ++

Когда мой ввод выглядит так:

11

Гарри Кейт Фред Кэрол

Моя матрица смежности должна помещать Гарри в [7] [7], Кейт в [7] [10], Фреда в [7] [5] и Кэрол в [7] [2]. Однако Кэрол и Кейт вставляются в другие места в пределах прил. матрица тоже. Я предполагаю, что это как-то связано с памятью стека и кучи, но я не уверен, как найти ошибку. Использование операторов cout, похоже, не вызывает никаких проблем.

Код ниже

#include <iostream>
#include <string>
#include <stdlib.h>
#include <iostream>
#include <sstream>
using namespace std;

class Element {

public:
    string name;
    int weight;
    string color;

    //default constructor
    Element(void) {
        name = "";
        weight = 0;
        color = "white";
    }

    //parameterized constructor
    Element(string first) {
        name = first;
        weight = 0;
        color = "white";
    }

    void setBlack() {
        color = "black";
    }
};

class AdjMatrix {

public:
    int size;
    Element ***adj_matrix;
    AdjMatrix(void) {
        size = 0;
        adj_matrix = NULL;
    }

    AdjMatrix(int n) {
        size = n; //sets the size to n
        adj_matrix = new Element **[size];
        for (int i = 0; i < size; i++) {
            adj_matrix[i] = new Element *[i];
        }
    }

    //Destructor class
    ~AdjMatrix(void) {
        delete adj_matrix;
        adj_matrix = NULL;
    }

    //initialize the array with empty elements
    void initialize_matrix() {
        Element *add_element = new Element("");
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++)
                adj_matrix[i][j] = add_element;
        }
    }
};


int convertToASCII(string letter)
{
   int x = letter.at(0);
   int index = x - 65;
    return index;
};

int main(int argc, char *argv[]) {

    string table_size;
    cout<<"";
    getline(cin,table_size);
    int size = atoi(table_size.c_str());
    AdjMatrix *myGraph = new AdjMatrix(size);
    myGraph->initialize_matrix();

string line;
getline(cin, line);
while (getline(cin,line))
{
    if (line.empty())
        break;

    else {

        int x = convertToASCII(line);
        stringstream linestream(line);
        string temp;

        while (linestream >> temp) {
            int z = convertToASCII(temp);
            myGraph->adj_matrix[x][z] = new Element(temp);
        }
    }
}

//Print graph
for (int i = 0; i < myGraph->size; i++) {
    for (int j = 0; j < myGraph->size; j++)
        cout<<"["<<i<<"]["<<j<<"]: "<<myGraph->adj_matrix[i][j]->name<<endl;
}

  return 0;
}

person OaklandFanatic    schedule 17.04.2014    source источник
comment
когда я запускаю программу, я получаю следующий результат [7][2]: Carol [7][3]: [7][4]: [7][5]: Fred [7][6]: [7][7]: Harry [7][8]: [7][9]: [7][10]: Kate Разве это не то, что вы ожидаете?   -  person    schedule 17.04.2014
comment
Кроме того, в initialize_matrix() вы выделяете несколько new Element(""), а затем в main() вы говорите myGraph->adj_matrix[x][z] = new Element(temp);, вызывая некоторую утечку памяти.   -  person    schedule 17.04.2014
comment
В вашем выводе вы заметите, что Кэрол также находится в [6] [10], а Кейт - в [8] [0]. Как бы я иначе инициализировал массив? Я попытался установить для каждого местоположения значение NULL, но это привело к сбою программы.   -  person OaklandFanatic    schedule 17.04.2014


Ответы (2)


В вашей программе есть следующая проблема, которую необходимо исправить.

 //default constructor
    Element(void) 

Конструктор должен быть определен как

 //default constructor
    Element()
  • Вам следует начать использовать std :: vector для своего 2D-массива. Это устранило бы ручное управление памятью. В современном C ++ не следует использовать необработанный указатель. Пожалуйста, обратитесь к следующему сообщению SO, в котором описывается, как использовать вектор для 2D-массива.

двумерный массив с использованием вектора в cpp

person Mantosh Kumar    schedule 17.04.2014
comment
Мне не разрешено использовать векторы в задании, иначе я бы это сделал, потому что с ними намного проще работать. Я обязательно внесу изменения в конструктор. - person OaklandFanatic; 17.04.2014
comment
У вас также есть утечки памяти. Посмотрите на свой деструктор - думаете ли вы, что один вызов delete удалит все выделения, которые вы сделали с помощью new ?. Класс также не следует правилу трех, поэтому ваш код легко сломать с помощью трехстрочной программы main (). - person PaulMcKenzie; 17.04.2014

В вашем AdjMatrix(int) ctor вы неправильно строите свою треугольную матрицу (если это то, что вы собираетесь делать). Попробуй это:

AdjMatrix(int n) {
    size = n; //sets the size to n
    adj_matrix = new Element **[size];
    for (int i = 0; i < size; i++) {
        adj_matrix[i] = new Element *[i + 1]; // Or size for a square matrix
    }
}
person ooga    schedule 17.04.2014
comment
Я пробовал это, но это приводит к сбою всей программы. Установка первого массива так, чтобы он указывал на другой массив того же размера, создает квадратную сетку, так что [0] [0] является первым местоположением, а не [0] [1] - person OaklandFanatic; 17.04.2014
comment
@OaklandFanatic - см. Этот ответ: stackoverflow.com/ questions / 23067857 / c-deep-copy-object / В нем описаны два способа динамического создания 2-мерного массива. Просто замените float на Element. Обратите внимание, как вы создаете и уничтожаете такие массивы, чего не может сделать ваш текущий код (разрушение). - person PaulMcKenzie; 17.04.2014
comment
@OaklandFanatic Если вам нужна квадратная матрица, поместите size там, где я положил i + 1. Ваша ошибка в том, что в вашем коде есть i. - person ooga; 17.04.2014
comment
@PaulMcKenzie благодарит за ссылку. У меня возникли проблемы с попыткой создать 2D-массив с объектом с двойным указателем, но я попробую этот метод еще раз. - person OaklandFanatic; 17.04.2014