Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/3: Рейтинг темы: голосов - 3, средняя оценка - 5.00
1 / 1 / 0
Регистрация: 19.01.2013
Сообщений: 28
1

Деструктор и конструктор копирования не работают

17.07.2015, 21:31. Просмотров 574. Ответов 4
Метки нет (Все метки)

Если котротко, то проблему можнео описать в двух словах: не могу написать деструктор и конструктор копирования к классу Матрица.
Подробнее
Пишу программу - расчет в цикле, а в расчете математика требует матриц, поэтому описал класс Matrix, там в расчете в цикле объекты этого класса создаются, работают куча функций, которые получают объекты класса Matrix в параметрах и выдают результат типа Matrix.
Расчет прекрасно работает при любых значениях. Но его надо использовать как часть более обширного расчета, в цикле.
При нек. значении счетчика цикла появляется: access violation.
Причем с каждым шагом цикла занимает больше памяти.
Смекнул, что я пренебрег написанием деструкутора в классе Matrix, из-за этого память и жрет.
Но когда пишу деструктор - не хочет работать.
В деструккторе вывожу сообщение: матрица такая-то удаляется. Удаляет первые 6 матриц (из которых одна - 3х3, остальные 1х3), а на седьмой на операторе
C++
1
delete[] c[i]
- ошибка: access violation.
Смекнул, что дело в том, что где-то происходит присваивание, создается временный объект, а значит, дело в том, что нужен еще конструктор копирования.
Но, видать, не могу теперь правильно описатьл конструктьолр копирования.
Пожалуйста,
помогите разобраться, дело ж вроде простое - к классу правильно написать деструктор и конструктор копирования
Коды
C++
1
2
3
4
5
6
class Matrix{
    int QLins, QCols //количество (quantity) строк и столбцов соответственно
    double**c;
    ...
    //методы
}
В том классе:
Конструкторы:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Matrix::Matrix(){
   QLins=1;
   QCols=1;
   c=new double*[QLins]
   for(int i=0; i<QLins; i++){
        c[i]=new double*[QCols]
   }
    c[0][0]=0;
}
Matrix::Matrix(int QLins, int QCols){ 
   this->QLins=QLins;
   this->QCols=QCols;
   c=new double*[QLins];
   for(int i=0; i<QLins; i++){
        c[i]=new double*[QCols];
   }
   for(int i=0; i<QLins; i++){
        for(int j=0; i<QCols; i++){
             c[i][j]=0;
       }
   }
}
Matrix::Matrix(double**c, int QLins, int QCols){ 
    if(this->c!=NULL){
        for(int i=0; i<QLins; i++){
             delete[]this->c[i];
        }
        delete[]this->c;
   }   
   this->QLins=QLins;
   this->QCols=QCols;
   c=new double*[QLins]
   for(int i=0; i<QLins; i++){
        c[i]=new double*[QCols]
   }
   for(int i=0; i<QLins; i++){
        for(int j=0; i<QCols; i++){
             this->c[i][j]=c[i][j];
       }
   }
}
Деструктор:
C++
1
2
3
4
5
6
7
8
9
Matrix::~Matrix(){
    if(c==NULL)delete c;
    else{
         for(int i=0; i<QLins; i++){
             delete[]c[i];
        }
        delete[]c;
    }
}
Вот в этом деструкторе ругается на delete[]c[i]. В ветку c==NULL не заходит, да, в прочем, у меня и конструкторы не позволяют создавать экземпляры с c==NULL, и ручаюсь, что в программе этого нет
А вот с конструктором копирования вообще интересно:
C++
1
2
3
Matrix::Matrix(Matrix&obj){
    ...
}
Вместо многоточия вначале было:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if(c!=NULL){
    for(int i=0; i<QLins; i++){
        delete[]c[i];
    }
    delete[]c;
}   
QLins=obj.QLins;
QCols=obj.QCols;
c=new double*[QLins]
for(int i=0; i<QLins; i++){
     c[i]=new double*[QCols]
}
for(int i=0; i<QLins; i++){
     for(int j=0; i<QCols; i++){
          c[i][j]=obj.c[i][j];
    }
}
Результат - ругается на delete[]c[i]; - access violation!
Тогда я догадался вставить в начало такой код:
C++
1
ShowMessage("Прежняя матрица: ("+IntToStr(QLins)+"x"+IntToStr(QCols)+"), Новая матрица: ("+IntToStr(obj.QLins)+"x"+IntToStr(obj.QCols)+")");
Результат еще интереснее - выдает что-то вроде:
Прежняя матрица: (1045430х5443330) Новая матрица: (3х1)
То есть, получается, временный объект создается как-то хитро, не по правилам, прописанных в конструкторах. Потому произвольные значения QLins и QCols. А тогда эти access violation легко объяснимы.
Если создано
c[3][1],
то обращение
с[1045430][5443330]
ничего другого, кроме как access violation, дать не может.
Я даже проверил:
C++
1
ShowMessage("Первый элемент матрицы: "+FloatToStr(c[0][0]);
ни к каким access violation приводит.

Но как же быть?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.07.2015, 21:31
Ответы с готовыми решениями:

Конструктор инициализации, конструктор копирования, деструктор
Я сделал почти задание по перегрузке операторов. Осталось одно, тоесть три: конструктор...

Создать класс "Вектор" и реализовать конструктор по умолчанию, конструктор копирования и деструктор
Всем доброго времени суток! нужна ваша помощь! нужно создать класс вектор и реализовать...

Конструктор копирования, деструктор при наследовании
Есть класс A и производный от него B. Написать конструктор копирования, деструкторы для обоих...

Определить конструктор без параметров, конструктор с одним параметром, конструктор с двумя параметрами, деструктор
Создать класс «матрица». Данный класс должен содержать элементы типа int, определяющие число строк,...

4
13537 / 7190 / 1723
Регистрация: 30.01.2014
Сообщений: 12,028
17.07.2015, 21:49 2
aviacheslav,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
Matrix::Matrix(){
   QLins=1;
   QCols=1;
   c=new double*[QLins];
   for(int i=0; i<QLins; i++){
        // c[i]=new double*[QCols];
        c[i]=new double[QCols]();
   }
}
Matrix::Matrix(int QLins, int QCols){
   this->QLins=QLins;
   this->QCols=QCols;
   c=new double*[QLins];
   for(int i=0; i<QLins; i++){
        // c[i]=new double*[QCols];
        c[i]=new double[QCols](); // (1) c[i][j] будет 0
   }
/* // Это лишнее, см. (1)
   for(int i=0; i<QLins; i++){
        for(int j=0; i<QCols; i++){
             c[i][j]=0;
       }
   }
*/
}
Matrix::Matrix(double** c, int QLins, int QCols){
   /* это категорически неверно, никакого объекта до вызов конструктора нет,
      поэтому мы не можем сравнивать еще неинициализированную память
   if(this->c!=NULL){
        for(int i=0; i<QLins; i++){
             delete[]this->c[i];
        }
        delete[]this->c;
   }
   */
   this->QLins=QLins;
   this->QCols=QCols;
   c=new double*[QLins];
   for(int i=0; i<QLins; i++){
        // c[i]=new double*[QCols];
        c[i]=new double[QCols];
   }
   for(int i=0; i<QLins; i++){
        for(int j=0; i<QCols; i++){
             this->c[i][j]=c[i][j];
       }
   }
}
 
Matrix::Matrix(Matrix const & other){
// Конструктор копирования
// тут тоже еще ничего удалять не надо, т.к. объекта до этого вообще не было. Это же конструктор.
   this->QLins=other.QLins;
   this->QCols=other.QCols;
   c=new double*[QLins];
   for(int i=0; i<QLins; i++){
        c[i]=new double[QCols];
   }
   for(int i=0; i<QLins; i++){
        for(int j=0; i<QCols; i++){
             this->c[i][j] = other.c[i][j];
       }
   }
}
См. комментарии.
В деструкторе достаточно этого:
C++
1
2
3
4
5
6
7
8
9
Matrix::~Matrix(){
    if(c)
    {
         for(int i=0; i<QLins; i++){
             delete[]c[i];
        }
        delete[]c;
    }
}
Еще нужно будет сделать оператор присваивания.

А вообще тут еще есть над чем работать.
1
2683 / 1855 / 552
Регистрация: 05.06.2014
Сообщений: 5,347
18.07.2015, 09:16 3
В дополнение к уже сказанному:
C++
1
2
3
4
5
6
7
8
9
10
11
class Matrix
{
    int rows, columns;
    double*data;
public:
    Matrix(int _rows,int _columns):rows(_rows),columns(_columns),data(new double[rows*columns]()){}
    Matrix():Matrix(1,1){}
    ~Matrix(){delete data;}
    double&value(int x,int y){return data[y*columns+x];}
    double value(int x,int y)const{return data[y*columns+x];}
};
А не возиться с массивом указателей, который еще и в цикле заполнять надо.
PS Так, для справки, в код выше нужны конструктор и оператор копирования.
0
:)
Эксперт С++
4763 / 3257 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
18.07.2015, 10:15 4
Renji,
C++
1
delete[] data;
Цитата Сообщение от DrOffset Посмотреть сообщение
А вообще тут еще есть над чем работать.
Например плюсовый код обрамлять плюсовыми же тегами, а не сишными
aviacheslav, рекомендация - ознакомиться с "правилом трех".
0
DrOffset
18.07.2015, 16:24     Деструктор и конструктор копирования не работают
  #5

Не по теме:

Цитата Сообщение от Tulosba Посмотреть сообщение
Например плюсовый код обрамлять плюсовыми же тегами, а не сишными
Спасибо, что обратил внимание, но такие вещи все-таки лучше в личку или через жалобу модератору сообщать :)

0
18.07.2015, 16:24
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.07.2015, 16:24
Привет! Вот еще темы с ответами:

Не могу сделать чтобы класс содержал основной конструктор и конструктор копирования
Разработать класс ThreeAngle для работы с плоскими треугольниками. В качестве членов-данных...

Конструктор класса, конструктор копирования запускается не тот который нужен
Есть такой конструктор: Neuron::Neuron(int iType_activation_funk) { this-&gt;iType_act =...

Не могу правильно сделать конструктор и конструктор копирования и принадлежность точки с заданными координатами треугольнику
#include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include &lt;conio.h&gt; #include &lt;windows.h&gt; #include...

С++. Конструктор, деструктор
Ребята!!! Помогите пожалуйста, не знаю как сделать это задание на С++. Нужно разработать класс...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.