Деструктор вызывается раньше, чем надо
#include <iostream>
using std::cout;
using std::endl;
class forlab
{
public:
std::string name;
int size;
int* arr;
forlab(std::string name, int size) {
this->size = size;
this->name = name;
*&arr = new int[size];
for (int i = 0; i < size; i++) {
arr[i] = 0;
}
}
forlab() {
this->name = "";
this->size = 0;
this->arr = 0;
}
~forlab() {
delete [] this->arr;
}
int& operator[] (const int index);
friend forlab operator+(const forlab a,const forlab b);
void show() {
for (int i = 0; i < size; i++) {
cout << this->arr[i] << " ";
}
}
};
int& forlab::operator[] (const int index)
{
return this->arr[index];
}
forlab operator+(const forlab a, const forlab b) {
forlab temp("", a.size+b.size);
for (int i = 0; i < a.size; i++) {
temp.arr[i] = a.arr[i];
}
int counter = a.size;
for (int i = 0; i < b.size; i++) {
temp.arr[counter] = b.arr[i];
counter++;
}
return temp;
}
int main() {
forlab ex1("first", 15);
forlab ex2("second", 20);
forlab ex3 = ex1 + ex2;
ex3.show();
return 0;
}
Деструктор вызывается раньше окончания программы из-за этого числа из динамического массива хранящегося в экземпляре ex3 не выводятся, а программа в деструкторе ловит исключение
Ответы (2 шт):
Когда operator+ завершается, temp уничтожается и в ex3 помещается копия temp. Но в копии хранится ссылка на массив arr, который освободился при вызове деструктора. Получается, что arr в ex3 - висячий указатель. Чтобы этого избежать, можно перегрузить конструктор копирования:
forlab(const forlab& f) {
size = f.size;
name = f.name;
arr = new int[size]; // заново выделяем память
memcpy(arr, f.arr, sizeof(int) * size); // копируем весь массив
}
У вас программа просто падает из-за двойного освобождения памяти в деструкторе - у вас нет копирующего конструктора, вот и получается, что копируется указатель (поверхностное копирование, генерируемое компилятором), а не память...
Допишите конструктор копирования, примерно такой
forlab(const forlab& f):name(f.name),size(f.size)
{
arr = new int[size];
for (int i = 0; i < size; i++) {
arr[i] = f.arr[i];
}
}
и все встанет на свои места...
P.S. А, ну да, еще и оператор присваивания, само собой... Но в данном случае он не то чтобы не нужен - просто он нигде не вызывается.
А чтобы убедиться - давайте допишем вывод в конструкторах-деструкторах:
#include <iostream>
using std::cout;
using std::endl;
class forlab
{
public:
std::string name;
int size;
int* arr;
forlab(std::string name, int size) {
cout << "Ctor " << name << endl;
this->size = size;
this->name = name;
*&arr = new int[size];
for (int i = 0; i < size; i++) {
arr[i] = 0;
}
}
forlab() {
cout << "Default ctor\n";
this->name = "";
this->size = 0;
this->arr = 0;
}
forlab(const forlab& f):name(f.name),size(f.size)
{
cout << "Copy ctor " << name << endl;
arr = new int[size];
for (int i = 0; i < size; i++) {
arr[i] = f.arr[i];
}
}
~forlab() {
cout << "Dtor " << name << endl;
delete [] this->arr;
}
int& operator[] (const int index);
friend forlab operator+(const forlab a,const forlab b);
void show() {
for (int i = 0; i < size; i++) {
cout << this->arr[i] << " ";
}
cout << endl;
}
};
int& forlab::operator[] (const int index)
{
return this->arr[index];
}
forlab operator+(const forlab a, const forlab b) {
forlab temp("", a.size+b.size);
for (int i = 0; i < a.size; i++) {
temp.arr[i] = a.arr[i];
}
int counter = a.size;
for (int i = 0; i < b.size; i++) {
temp.arr[counter] = b.arr[i];
counter++;
}
return temp;
}
int main() {
forlab ex1("first", 15);
forlab ex2("second", 20);
forlab ex3 = ex1 + ex2;
ex3.show();
return 0;
}
Скомпилируйте, запустите, убедитесь в соответствии конструкторов деструкторам:
Ctor first
Ctor second
Copy ctor second
Copy ctor first
Ctor
Dtor first
Dtor second
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Dtor
Dtor second
Dtor first
Посмотрите, например, тут. Теперь помогло?
Кстати, если вы замените
forlab operator+(const forlab a, const forlab b) {
на
forlab operator+(const forlab & a, const forlab & b) {
то избежите двух лишних копирований. Попробуйте сами..