Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
awpe
2 / 2 / 0
Регистрация: 23.11.2011
Сообщений: 87
#1

delete внутри класса для самого класса - C++

05.04.2013, 06:45. Просмотров 923. Ответов 24
Метки нет (Все метки)

Доброго времени суток, пишу программу для работы с матрицами. По условию дали лишь несколько библиотек, ни векторов ни cstdio. Для динамического выделения памяти только new и delete. Итак что есть: класс CMatrix, основной элемент - это массив рядов матрицы, каждый ряд представлен классом CRow, который представляет собой массив double.

CRow:

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
class CRow {
public:
    CRow() {
        RowSize = 0;
    };
    CRow(int Cols) {
        RowElements = new double [Cols];
        for (int i = 0; i < Cols; i++) {
            RowElements[i] = 0.0;
        }
        RowSize = Cols;
    };
    CRow & operator=(const CRow & Old) {
        if (this == &Old) {
            return *this;
        }
        RowSize = Old.RowSize;
        RowElements = new double[Old.RowSize];
        for (int i = 0; i < Old.RowSize; i++) {
            RowElements[i] = Old.RowElements[i];
        }
        return *this;
    };
    ~CRow() {
        delete [] RowElements;
    };
    double & operator[](const int & ColNumber)const {
        return RowElements[ColNumber];
    };
    friend std::ostream & operator<<(std::ostream& os, const CRow& Row) {
        os << Row.RowElements[0];
        for (int i = 1; i < Row.RowSize; i++) {
            os << ", " << Row.RowElements[i];
        }
        return os;
    };
    friend class CMatrix;
protected:
    double * RowElements;
    int RowSize;
};
CMatrix:

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
65
66
67
class CMatrix {
public:
 
    CMatrix(int RCount, int ColsCount) {
        Rows = new CRow*[RCount];
        for (int i = 0; i < RCount; i++) {
            Rows[i] = new CRow(ColsCount);
        }
        RowsCount = RCount;
        ColumnsCount = ColsCount;
    };
 
    CMatrix(const CMatrix & Old) : RowsCount(Old.RowsCount), ColumnsCount(Old.ColumnsCount) {
        Rows = new CRow*[Old.RowsCount];
        for (int i = 0; i < RowsCount; i++) {
            Rows[i] = new CRow;
            *Rows[i] = *Old.Rows[i];
        }
    };
 
    ~CMatrix() {
        for (int i = 0; i < RowsCount; i++) {
            delete Rows[i];
        }
        delete [] Rows;
    };
 
    friend std::ostream & operator<<(std::ostream& os, const CMatrix& CM) {
        for (int i = 0; i < CM.RowsCount - 1; i++) {
            os << "{" << *CM.Rows[i] << " }," << std::endl;
        }
        os << "{" << *CM.Rows[CM.RowsCount - 1] << "}" << std::endl;
        return os;
    };
    CRow & operator[](const int & RowNumber)const {
        return *Rows[RowNumber];
    };
    friend class CRow;
 
    friend std::istream & operator>>(std::istream& is, CMatrix& CM) {
//здесь читается поток is потом надо этот поток отправить в матрицу, алгорит такой - читается поток на предмет 
//нормального формата, заодно выясняется сколько там рядов и столбцов
// потом создается временная матрица типа CMatrix, вызывается конструктор которму указывается сколько будет рядов 
//и столбцов
//потом абсолютно тем же алгоритмом что и в первом пункте (после is.seekg(0, is.beg); ) делается проход по is с записью 
//значений в матрицу.
// вот объясните мне неразумному - если нет реаалок то это единственый способ? Все что я могу еще придумать с new 
// это при нахождении элемента который выходит за границы размерности текущей матрицы-объекта, создавать 
//временный объект туду все сливать потом старый удалять и копировать туда указатель на новый... Мне кажется это 
//глупость, поэтому я сначала записываю все значения во временную матрицу а потом уже удаляю старую и приписываю 
//указатель. НО! валгринд потом находит один не освобожденный блок...
};
 
protected:
    CRow ** Rows;
    enum States {
        State_StartMatrix,
        State_StartLine,
        State_EndLine,
        State_EndMatrix,
        State_GotNumber,
        State_NextNumber,
        State_Error
    };
    int RowsCount;
    int ColumnsCount;
};
Вся программа как есть:
Кликните здесь для просмотра всего текста
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
#ifndef __PROGTEST__
#include <iostream>
#include <sstream>
#include <iomanip>
#endif /* __PROGTEST__ */
 
class CRow {
public:
 
    CRow() {
        RowSize = 0;
    };
 
    CRow(int Cols) {
        RowElements = new double [Cols];
        for (int i = 0; i < Cols; i++) {
            RowElements[i] = 0.0;
        }
        RowSize = Cols;
    };
 
    CRow & operator=(const CRow & Old) {
        if (this == &Old) {
            return *this;
        }
        RowSize = Old.RowSize;
        RowElements = new double[Old.RowSize];
        for (int i = 0; i < Old.RowSize; i++) {
            RowElements[i] = Old.RowElements[i];
        }
        //std::cout << "padla" << std::endl;
        return *this;
    };
 
    ~CRow() {
        //std::cout << "padla" << std::endl;
        delete [] RowElements;
    };
 
 
    double & operator[](const int & ColNumber)const {
        return RowElements[ColNumber];
    };
 
    friend std::ostream & operator<<(std::ostream& os, const CRow& Row) {
        os << Row.RowElements[0];
        for (int i = 1; i < Row.RowSize; i++) {
            os << ", " << Row.RowElements[i];
        }
        return os;
    };
    friend class CMatrix;
protected:
    double * RowElements;
    int RowSize;
};
 
class CMatrix {
public:
 
    CMatrix(int RCount, int ColsCount) {
        Rows = new CRow*[RCount];
        for (int i = 0; i < RCount; i++) {
            Rows[i] = new CRow(ColsCount);
        }
        RowsCount = RCount;
        ColumnsCount = ColsCount;
    };
 
    CMatrix(const CMatrix & Old) : RowsCount(Old.RowsCount), ColumnsCount(Old.ColumnsCount) {
        Rows = new CRow*[Old.RowsCount];
        for (int i = 0; i < RowsCount; i++) {
            Rows[i] = new CRow;
            *Rows[i] = *Old.Rows[i];
        }
    };
 
    ~CMatrix() {
        for (int i = 0; i < RowsCount; i++) {
            delete Rows[i];
        }
        delete [] Rows;
    };
 
    friend std::ostream & operator<<(std::ostream& os, const CMatrix& CM) {
        for (int i = 0; i < CM.RowsCount - 1; i++) {
            os << "{" << *CM.Rows[i] << " }," << std::endl;
        }
        os << "{" << *CM.Rows[CM.RowsCount - 1] << "}" << std::endl;
        return os;
    };
    CRow & operator[](const int & RowNumber)const {
        return *Rows[RowNumber];
    };
    friend class CRow;
 
    friend std::istream & operator>>(std::istream& is, CMatrix& CM) {
        int RowSize = 0;
        int LinesCount = 0;
        int ColsTmp = 0;
        double d;
        char c;
        bool WhileBool = true;
        States state = State_StartMatrix;
        while (WhileBool) {
            switch (state) {
                case State_StartMatrix:
                    is >> std::skipws >> c;
                    if (c == '{') {
                        state = State_StartLine;
                    } else {
                        state = State_Error;
                    }
                    break;
                case State_StartLine:
                    is >> std::skipws >> c;
                    if (c == '{') {
                        state = State_NextNumber;
                    } else {
                        state = State_Error;
                    }
                    break;
                case State_NextNumber:
                    is >> std::skipws >> d;
                    if (!is.fail()) {
                        //RowElements[LinesCount][ColsTmp] = d;
                        ColsTmp++;
                        //cout << "num: '" << d << "'" << endl;
                        state = State_GotNumber;
                    } else {
                        state = State_Error;
                    }
                    break;
                case State_GotNumber:
                    is >> std::skipws >> c;
                    if (c == ',') {
                        state = State_NextNumber;
                    } else if (c == '}') {
                        state = State_EndLine;
 
                    } else {
                        state = State_Error;
                    }
                    break;
                case State_EndLine:
                    LinesCount++;
                    if (LinesCount > 1) {
                        if (RowSize != ColsTmp) {
                            state = State_Error;
                            break;
                        }
                    }
                    if (LinesCount == 1) {
                        RowSize = ColsTmp;
                    }
                    ColsTmp = 0;
                    is >> std::skipws >> c;
                    if (c == ',') {
                        state = State_StartLine;
                    } else if (c == '}') {
                        state = State_EndMatrix;
                    } else {
                        state = State_Error;
                    }
                    break;
                case State_EndMatrix:
                    WhileBool = false;
                    break;
                case State_Error:
                    is.setstate(std::ios::failbit);
                    WhileBool = false;
                    break;
            }
        }
 
        if (!is.fail()) {
 
 
            //            for (int i = 0; i < LinesCount; i++) {
            //                for (int j = 0; j < RowSize - 1; j++) {
            //                    std::cout << "" << RowElements[i][j] << ",";
            //                }
            //                std::cout << "" << RowElements[i][RowSize - 1] << "";
            //                std::cout << std::endl;
            //            }
            //            std::cout << "Rows:\t" << LinesCount << std::endl;
            //            std::cout << "Cols:\t" << RowSize << std::endl;
 
 
            CMatrix *tmpMatrix = new CMatrix(LinesCount, RowSize);
            is.seekg(0, is.beg);
            LinesCount = 0;
            RowSize = 0;
            ColsTmp = 0;
 
 
            bool WhileBool = true;
            States state = State_StartMatrix;
            while (WhileBool) {
                switch (state) {
                    case State_StartMatrix:
                        is >> std::skipws >> c;
                        if (c == '{') {
                            state = State_StartLine;
                        } else {
                            state = State_Error;
                        }
                        break;
                    case State_StartLine:
                        is >> std::skipws >> c;
                        if (c == '{') {
                            state = State_NextNumber;
                        } else {
                            state = State_Error;
                        }
                        break;
                    case State_NextNumber:
                        is >> std::skipws >> d;
                        if (!is.fail()) {
                            //RowElements[LinesCount][ColsTmp] = d;
                            tmpMatrix->Rows[LinesCount]->operator [](ColsTmp) = d;
                            ColsTmp++;
                            //cout << "num: '" << d << "'" << endl;
                            state = State_GotNumber;
                        } else {
                            state = State_Error;
                        }
                        break;
                    case State_GotNumber:
                        is >> std::skipws >> c;
                        if (c == ',') {
                            state = State_NextNumber;
                        } else if (c == '}') {
                            state = State_EndLine;
                        } else {
                            state = State_Error;
                        }
                        break;
                    case State_EndLine:
                        LinesCount++;
                        if (LinesCount > 1) {
                            if (RowSize != ColsTmp) {
                                state = State_Error;
                                break;
                            }
                        }
                        if (LinesCount == 1) {
                            RowSize = ColsTmp;
                        }
                        ColsTmp = 0;
                        is >> std::skipws >> c;
                        if (c == ',') {
                            state = State_StartLine;
                        } else if (c == '}') {
                            state = State_EndMatrix;
                        } else {
                            state = State_Error;
                        }
                        break;
                    case State_EndMatrix:
                        WhileBool = false;
                        break;
                    case State_Error:
                        is.setstate(std::ios::failbit);
                        WhileBool = false;
                        break;
                }
            }
 
 
 
            for (int i = 0; i < CM.RowsCount; i++) {
                delete CM.Rows[i];
            }
            delete [] CM.Rows;
 
            
            CM = *tmpMatrix;
 
            return is;
        }
        return is;
    };
 
 
 
protected:
    CRow ** Rows;
 
    enum States {
        State_StartMatrix,
        State_StartLine,
        State_EndLine,
        State_EndMatrix,
        State_GotNumber,
        State_NextNumber,
        State_Error
    };
    int RowsCount;
    int ColumnsCount;
};
 
int main(int argc, char** argv) {
    std::istringstream is;
    std::ostringstream os;
 
 
    CMatrix a(2, 3);
    a[0][0] = 1;
    a[0][1] = 2;
    a[0][2] = 3;
    a[1][0] = 4;
    a[1][1] = 5;
    a[1][2] = 6;
    const CMatrix b = a;
    std::cout << b[1][2] << std::endl;
 
    CMatrix d(1, 1);
    d[0][0] = -1;
 
    std::cout << d;
 
 
 
 
    is . clear();
    is . str("{ { 1.1782, 2, 3, 4 }, { 4, 3, 2, 1 } } ");
 
 
    is >> a;
 
 
    return 0;
}


Внутри оператора >> класса CMatrix я втсавил комментарии и вопрос.

В общем моя проблема в том что я привык в malloc/realloc когда учил си, для динамического распределения памяти, каждый раз создавать временный объект чтобы скопировать туда то что есть и потом приравнивать указатели и удлалять старый... Вероятно я просто не умею готовить new/delete расскажите/научите что я делаю не так, где можно было бы решить проще? кстати из за отсутствия realloc в программе приходится в операторе >> два раза один и тот же кусок кода использовать, так как на ходу увеличивать размер не получится. Два класса нужны, чтобы перегрузить оператор [][];

И еще раз нет ни векторов ни стрингов - ничего кроме указынных под спойлером библиотек.

Добавлено через 2 минуты
P.S. Если вы студент FIT, большая просьба не копипастить, все равно потом я докажу что это мой код, но время потеряют все...

Добавлено через 7 минут
Валгринд показывает утечку здесь:
C++
1
CMatrix *tmpMatrix = new CMatrix(LinesCount, RowSize);
что странно, ведь я делаю вот так:
C++
1
2
3
4
            for (int i = 0; i < CM.RowsCount; i++) {
                delete CM.Rows[i];
            }
            delete [] CM.Rows;
что очищает все динамические структуры в текущей матрице, потом вот так:
C++
1
CM = *tmpMatrix;
т.е. имели ссылку на CM типа CMatrix, данный вызов, как я понимаю вызывает конструктор для CMatrix, создается мелкая копия (т.е. только указатели присваиваются) и вуаля - в CM теперь объект tmpMatrix, где тут утечка?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.04.2013, 06:45     delete внутри класса для самого класса
Посмотрите здесь:
C++ Заполнение вектора класса внутри самого класса
Использование указателей на функции-члены внутри самого класса C++
C++ С++, delete в деструкторе класса не видит переменные, создаваемые new в конструкторе класса
Удаление экземпляра класса в функции самого класса (Ошибка при отладке) C++
BST дерево. Инициализация класса внутри класса C++
C++ Видимость экземпляра класса внутри класса
Объявление дружественного класса внутри класса C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
В астрале
Эксперт С++
7967 / 4729 / 320
Регистрация: 24.06.2010
Сообщений: 10,539
Завершенные тесты: 3
05.04.2013, 13:20     delete внутри класса для самого класса #21
awpe, Когда хранятся не ресурсы требующие ручного выделения/очистки/открытия/закрытия etc, когда имплементируется модель Copy-on-Write
lemegeton
2918 / 1347 / 134
Регистрация: 29.11.2010
Сообщений: 2,721
05.04.2013, 13:23     delete внутри класса для самого класса #22
awpe, у вас по ограничениям можно пользоваться шаблонами?
awpe
2 / 2 / 0
Регистрация: 23.11.2011
Сообщений: 87
05.04.2013, 13:53  [ТС]     delete внутри класса для самого класса #23
lemegeton, да конечно
awpe
2 / 2 / 0
Регистрация: 23.11.2011
Сообщений: 87
06.04.2013, 18:37  [ТС]     delete внутри класса для самого класса #24
Задача решена, всем большое спасибо!
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.04.2013, 09:27     delete внутри класса для самого класса
Еще ссылки по теме:
C++ Методы класса внутри определения класса
Инициализация класса A внутри класса B C++
Как перегрузить операцию = для присваивания элементам структуры внутри класса значений? C++
Создать для класса виртуальный метод, возвращающий уникальный идентификатор класса C++
C++ Создать конструктор копий и оператор присваивания для класса компьютер и члена класса марка

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

Или воспользуйтесь поиском по форуму:
_Alexander
12 / 12 / 1
Регистрация: 05.11.2012
Сообщений: 49
08.04.2013, 09:27     delete внутри класса для самого класса #25
Цитата Сообщение от awpe Посмотреть сообщение
_Alexander, CMatrix(const CMatrix & Old) - разве не он?
Он, а для класса CRow?
Yandex
Объявления
08.04.2013, 09:27     delete внутри класса для самого класса
Ответ Создать тему
Опции темы

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