У меня есть класс с именем 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
Может кто-нибудь объяснить мне, почему деструктор срабатывает быстрее в последнем коде ?! и как я могу предотвратить это
заранее спасибо
Ваш оператор присваивания возвращается *this
по стоимости, делая копию этого. Обычно вы бы вернули ссылку:
Matrix& Matrix::operator=(const Matrix& A)
// ^
Копирование выполняется с использованием неявного конструктора копирования, который просто копирует указатель на член. Теперь у вас есть два объекта, которые думают, что они «владеют» выделенной памятью. Временное значение, возвращаемое operator=
вскоре уничтожается, удаляя память и оставляя y
с висящим указателем; вы получаете ошибку, когда y
пытается удалить ту же память во второй раз.
Вот почему классы, которые управляют ресурсами, должны следовать Правило трех, чтобы гарантировать, что они безопасны для копирования. Стандартные контейнеры, такие как std::vector
сделай это; Обычно это хорошая идея, а не управлять памятью самостоятельно.
Причина в том, что ваш измененный оператор присваивания копии возвращает по значению который создает копию матрицы, возвращает ее, а затем уничтожает.
Каноническая подпись для вашего оператора присвоения копии будет Matrix& Matrix::operator=(const Matrix& A)
(обратите внимание, что я возвращаюсь по неконстантной ссылке).
РЕДАКТИРОВАТЬ: имейте в виду, что если вы просто используете vector
все это управление памятью просто исчезает, и все эти функции могут использовать значения по умолчанию компилятора. Хотя, если вы на самом деле храните bool
s в матрице, vector<bool>
специализируется, и вы должны просто убедиться, что понимаете, как эта специализация взаимодействует с вашим кодом.