Vector :: push_back () дает нарушение прав чтения - PullRequest
0 голосов
/ 05 мая 2018

У меня есть проблема с моим классом, которая появляется только при попытке добавить один из моих объектов в вектор.

Назначение работает нормально , если это не происходит при попытке вставить в вектор (это приводит к следующей ошибке при освобождении памяти: выдано исключение: нарушение прав чтения this->elements было 0xCEDECEDF).

Вот мой оператор присваивания и мой конструктор копирования. Обратите внимание, что elements является указателем int**.

    Matrice& Matrice::operator=(const Matrice& other)
{
    if (elements)
    {
        for (size_t i = 0; i < numberoflines; ++i)
            if (elements[i])
                delete[] elements[i];
        delete[] elements;
    }
    id = other.id;
    numberofcols= other.numberofcols;
    numberoflines= other.numberoflines;
    elements = new int*[numberoflines];
    for (size_t i = 0; i < numberoflines; ++i)
        elements[i] = new int[numberofcols];
    for (size_t i = 0; i < numberoflines; ++i)
        for (size_t j = 0; j < numberofcols; ++j)
            elements[i][j] = other.elements[i][j];
    return *this;
}
Matrice::Matrice(const Matrice& other) {
    *this = other;
}

Вот заголовок класса Matrice (Matrix):

#pragma once
#include<iostream>
class Matrice {
public:
    friend std::istream& operator>>(std::istream&, Matrice&);
    friend std::ostream& operator<<(std::ostream&, const Matrice&);
    Matrice(const unsigned, const unsigned, const unsigned);
    Matrice();
    Matrice(const Matrice&);
    ~Matrice();
    Matrice& operator=(const Matrice&);
    int operator~()const;
    bool operator<(const Matrice&)const;
private:
    unsigned id;
    unsigned numberoflines;
    unsigned numberofcols;
    int** elements;
};

Вот конструкторы и деструктор:

    Matrice::Matrice(unsigned id, unsigned numberoflines, unsigned numberofcols) {
    this->id = id;
    this->numberoflines = numberoflines;
    this->numberofcols = numberofcols;
    elements = new int*[numberoflines];
    for (size_t i = 0; i < numberoflines; ++i)
        elements[i] = new int[numberofcols];
}
Matrice::Matrice() {
    numberofcols = 1;
    numberoflines = 1;
    elements = new int*[numberoflines];
    for (size_t i = 0; i < numberoflines; ++i)
        elements[i] = new int[numberofcols];
}
Matrice::~Matrice() {
    if (elements) {
        for (size_t i = 0; i < numberoflines; ++i)
            if (elements[i])
                delete[] elements[i];
        delete[] elements;
    }
}

И, наконец, я просто делаю это в main :

 std::vector<Matrice> vec;
    Matrice obj;
    vec.push_back(obj);

1 Ответ

0 голосов
/ 05 мая 2018

Ваш конструктор копирования вызывает оператор присваивания. Оператор присваивания начинается с этого кода:

if (elements)
{
    for (size_t i = 0; i < numberoflines; ++i)
        if (elements[i])
            delete[] elements[i];
    delete[] elements;
}

Это вызовет проблемы в конструкторе копирования, поскольку ничто в конструкторе копирования не инициализировало elements, поэтому оно будет указывать на случайное место в памяти. В вашем случае это было 0xCEDECEDF. Следовательно, elements не равен нулю, что в C ++ всегда оценивается как true, поэтому приведенный выше код будет пытаться удалить память, которая фактически не выделена.

После добавления строки elements = nullptr; в конструктор копирования значение elements теперь интерпретируется как false, поэтому блок if пропускается, а код освобождения не вызывается.

Другой способ сделать это в C ++ 11 , что, по мнению IMHO, более разумно, - инициализировать nullptr в самом объявлении класса:

    unsigned numberofcols;
    int** elements = nullptr; // CHANGE HERE
};

Таким образом, компилятор инициализирует elements каждый раз, когда создается новый объект, и вам не нужно беспокоиться о том, чтобы забыть сделать это в одном из ваших конструкторов.

Кстати, ваш конструктор копирования имеет недосмотр; сначала убедитесь, что this и other - это не один и тот же объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...