почему вызов оператора присваивания запускает функцию уничтожения?

У меня есть класс с именем Matrix с двумерным указателем bool ** matrix.

посмотрите на этот код:

void Matrix::operator=(const Matrix& A){

cout << "address in A : " << A.matrix << endl ;
cout << "address in y : " << matrix << endl ;

//return *this;
}

Я назвал мой оператор = в моей основной функции следующим образом:

Matrix x(3,5);
Matrix y(3,5);

x.set(1,4,1);
cout << "address out X: " << x.matrix << endl;
cout << "address out Y: " << y.matrix << endl;
y = x;
cout << "address out X: " << x.matrix << endl;
cout << "address out Y: " << y.matrix << endl;

Деструктор выглядит так:

Matrix::~Matrix(){
cout << "address de : " << matrix <<endl;
for (int i=0;i<m;i++)
delete[] matrix[i];
delete[] matrix;
cout << "address de finish : " << matrix <<endl;
}

Когда я запускаю свою программу в xcode, я получаю:

address out X: 0x100103ab0
address out Y: 0x100103af0
address in A : 0x100103ab0
address in y : 0x100103af0
address out X: 0x100103ab0
address out Y: 0x100103af0
address de : 0x100103af0
address de finish : 0x100103af0
address de : 0x100103ab0
address de finish : 0x100103ab0

и это выглядит хорошо, но когда я изменяю функцию оператора = так:

Matrix Matrix::operator=(const Matrix& A){

cout << "address in A : " << A.matrix << endl ;
cout << "address in y : " << matrix << endl ;

return *this;
}

Я получаю это в результате:

address out X: 0x100103ab0
address out Y: 0x100103af0
address in A : 0x100103ab0
address in y : 0x100103af0
address de : 0x100103af0
address de finish : 0x100103af0
address out X: 0x100103ab0
address out Y: 0x100103af0
address de : 0x100103af0
Thesis(26190) malloc: *** error for object 0x100103b10: pointer being freed was not allocated

Может кто-нибудь объяснить мне, почему деструктор срабатывает быстрее в последнем коде ?! и как я могу предотвратить это

заранее спасибо

0

Решение

Ваш оператор присваивания возвращается *this по стоимости, делая копию этого. Обычно вы бы вернули ссылку:

Matrix& Matrix::operator=(const Matrix& A)
//    ^

Копирование выполняется с использованием неявного конструктора копирования, который просто копирует указатель на член. Теперь у вас есть два объекта, которые думают, что они «владеют» выделенной памятью. Временное значение, возвращаемое operator= вскоре уничтожается, удаляя память и оставляя y с висящим указателем; вы получаете ошибку, когда y пытается удалить ту же память во второй раз.

Вот почему классы, которые управляют ресурсами, должны следовать Правило трех, чтобы гарантировать, что они безопасны для копирования. Стандартные контейнеры, такие как std::vector сделай это; Обычно это хорошая идея, а не управлять памятью самостоятельно.

3

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

Причина в том, что ваш измененный оператор присваивания копии возвращает по значению который создает копию матрицы, возвращает ее, а затем уничтожает.

Каноническая подпись для вашего оператора присвоения копии будет Matrix& Matrix::operator=(const Matrix& A) (обратите внимание, что я возвращаюсь по неконстантной ссылке).

РЕДАКТИРОВАТЬ: имейте в виду, что если вы просто используете vector все это управление памятью просто исчезает, и все эти функции могут использовать значения по умолчанию компилятора. Хотя, если вы на самом деле храните bools в матрице, vector<bool> специализируется, и вы должны просто убедиться, что понимаете, как эта специализация взаимодействует с вашим кодом.

7

По вопросам рекламы [email protected]