Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.61/18: Рейтинг темы: голосов - 18, средняя оценка - 4.61
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
1

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

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

Author24 — интернет-сервис помощи студентам
Доброго времени суток, пишу программу для работы с матрицами. По условию дали лишь несколько библиотек, ни векторов ни 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, где тут утечка?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.04.2013, 06:45
Ответы с готовыми решениями:

Заполнение вектора класса внутри самого класса
class A { private: int a; public: A() { a = 0; }; A get(vector &lt;A&gt;* vec)

Использование указателей на функции-члены внутри самого класса
День добрый форум! Возник такой вопрос. В классе А есть 3 функции и массив, в котором хранятся...

С++, delete в деструкторе класса не видит переменные, создаваемые new в конструкторе класса
#include &quot;stdafx.h&quot; #include &quot;iostream&quot; #include &quot;math.h&quot; using namespace std; class fun {...

Можно ли создать объект класса с таким же именем как у самого класса?
Можно ли создать объект класса с таким же именем как у самого класса? Ну или как то обойти эту...

24
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
05.04.2013, 07:12  [ТС] 2
Сделал так - очищаю текущую матрицу, потом скопировал код конструктора CMatrix прямо в тело опертора >> т..е там выделяются новые значние сразу для CM потом сразу же туда и записываются... Работать работает, нравится - нет Я не понимаю в чем была ошибка с временным объектом?

Добавлено через 44 секунды
Croessmah, ?
0
4773 / 2582 / 894
Регистрация: 29.11.2010
Сообщений: 5,590
05.04.2013, 09:02 3
Цитата Сообщение от awpe Посмотреть сообщение
friend std::istream & operator>>(std::istream& is, CMatrix& CM) {
//здесь читается поток is потом надо этот поток отправить в матрицу, алгорит такой - читается поток на предмет
//нормального формата, заодно выясняется сколько там рядов и столбцов
// потом создается временная матрица типа CMatrix, вызывается конструктор которму указывается сколько будет рядов
//и столбцов
//потом абсолютно тем же алгоритмом что и в первом пункте (после is.seekg(0, is.beg); ) делается проход по is с записью
//значений в матрицу.
// вот объясните мне неразумному - если нет реаалок то это единственый способ? Все что я могу еще придумать с new
// это при нахождении элемента который выходит за границы размерности текущей матрицы-объекта, создавать
//временный объект туду все сливать потом старый удалять и копировать туда указатель на новый... Мне кажется это
//глупость, поэтому я сначала записываю все значения во временную матрицу а потом уже удаляю старую и приписываю
//указатель. НО! валгринд потом находит один не освобожденный блок...
};
Так не получится. Ваша матрица не умеет динамически изменяться. Либо вы её научите хотя бы добавлять элементы в хвост, либо считывайте значения в некий буффер, а потом скармливайте матрице. В любом случае по памяти будет оверхеад.

Вы, кстати, заметили, что написали два практически идентичных класса?
Не хотите попробовать их объединить?
0
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
05.04.2013, 09:16  [ТС] 4
Цитата Сообщение от lemegeton Посмотреть сообщение
Не хотите попробовать их объединить?
Я бы с радостью, но мне нужна перегрузка [][] не знаю как ее в одном классе организовать...
0
4773 / 2582 / 894
Регистрация: 29.11.2010
Сообщений: 5,590
05.04.2013, 09:30 5
Не надо в одном. Попробуйте сделать хранилище хранилища. Тогда перегрузка [][] сама собой образуется.

Грубо говоря, я предлагаю завелосипедить свой собственный std::vector. Это не так сложно, как кажется на первый взгляд, ваш CRow уже более чем на половину похож.

Ну и сделать собственный std::vector<std::vector> matrix;
0
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
05.04.2013, 09:50  [ТС] 6
Цитата Сообщение от lemegeton Посмотреть сообщение
Грубо говоря, я предлагаю завелосипедить свой собственный std::vector.
Вы не находите что это лишняя работа? Почему вы думаете, что мне нужна вся функциональность вектора с точки зрения хранения информации? Тем более, что бы я там не написал, все равно упрусь в проблему с new, т.к. именно на нем он и сделан
0
4773 / 2582 / 894
Регистрация: 29.11.2010
Сообщений: 5,590
05.04.2013, 09:59 7
Цитата Сообщение от awpe Посмотреть сообщение
Вы не находите что это лишняя работа?
Вы проделываете лишнюю работу, изображая два класса с одинаковой функциональностью. Если вы замените его одним, более полным, вы уменьшите работу и увеличите гибкость решения, что немаловажно.

Цитата Сообщение от awpe Посмотреть сообщение
Почему вы думаете, что мне нужна вся функциональность вектора с точки зрения хранения информации?
Потому что для ввода в том виде, каком вы хотите, вам нужно уметь изменять хранилище на лету.

Цитата Сообщение от awpe Посмотреть сообщение
все равно упрусь в проблему с new
Возможно. Зависит от выбранного способа хранения данных. В любом случае, проблему можно решить копированием.

Цитата Сообщение от awpe Посмотреть сообщение
vector вроде все же на malloc сделан
stl::vector сделан на аллокаторах. Это довольно сложный концепт, но аллокатор по-умолчанию для вектора реализован на плюсовых способах выделения памяти (aka new и delete), не на malloc'ах.

Кстати, realloc не панацея. Разве что он может без вашего участия скопировать данные в памяти, если увеличение выделенного блока невозможно.
Проблема с new у вас мнимая, способы выделения памяти практически ничем не отличаются друг от друга.
0
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
05.04.2013, 11:21  [ТС] 8
Если я вас правильно понял, вы предлагаете реализовать группу классов вектор, а потом работать с моим заданием из одного класса? Или вы имели ввиду, что можно вообще все перегрузки [][] внутри одного класса делать?
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
05.04.2013, 11:46 9
awpe, Пример

C++
1
2
std::vector<std::vector<int>> v{{1},{2}};
std::cout << v[0][0] << std::endl;
0
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
05.04.2013, 11:50  [ТС] 10
Подскажите тогда механизм по которому вектор очищает сам себя?
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
05.04.2013, 11:51 11
awpe, Деструктор же.
0
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
05.04.2013, 11:55  [ТС] 12
Предлагаете как и в векторе выделять память в геометрической прогрессии? И хранить количество активных/используемых элементов?
0
12 / 12 / 3
Регистрация: 05.11.2012
Сообщений: 49
05.04.2013, 11:56 13
ИМХО не помешает также конструктор копий
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
05.04.2013, 12:06 14
awpe, А вы знаете еще вариант, как использовать динамический массив, учитывая что возможна переаллокация памяти? В сущности, все зависит от задачи, очевидно, коэффицент равный приблизительно 1.5 - идеален для вектора (но в нем как бэ могут содержаться оооочень много элементов).
0
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
05.04.2013, 12:12  [ТС] 15
_Alexander, CMatrix(const CMatrix & Old) - разве не он?


ForEveR, Я понял, у меня и так что то подобное уже получается, за исключением переаллокации, которой я хотел избежать...
0
4773 / 2582 / 894
Регистрация: 29.11.2010
Сообщений: 5,590
05.04.2013, 12:29 16
Цитата Сообщение от awpe Посмотреть сообщение
Предлагаете как и в векторе выделять память в геометрической прогрессии? И хранить количество активных/используемых элементов?
Выделяйте в арифметической прогрессии.
Цитата Сообщение от awpe Посмотреть сообщение
Я понял, у меня и так что то подобное уже получается, за исключением переаллокации, которой я хотел избежать...
Вы её не избежите, используя realloc. Она лишь станет неявной.

Вы можете уменьшить переаллокацию, воспользовавшись связными списками, но это замедлит доступ к данным, что довольно критично, поскольку изменение размера требуется редко, а доступ к данным -- частов.

Что я хочу сказать -- не парьтесь, копируйте данные при реаллокации. Легкореализуемой альтернативы нет, иначе бы она была реализована в std::vector.
1
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
05.04.2013, 12:54 17
awpe, Вцелом, т.к. матрица квадратная можно сделать проще. Так же, так как выделяется память сразу - переаллокация не нужна. Пример сейчас дам. А, нет. Слегка подгоняю. Но сама матрица расти не должна в любом случае.

Добавлено через 9 минут
Сам класс выглядит довольно просто.

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
#include <iostream>
#include <cstring>
 
class Matrix
{
public:
   Matrix(size_t rows, size_t cols) : rows_(rows), cols_(cols)
   {
      allocate();
   }
   Matrix(const Matrix& rhs) : rows_(rhs.rows_), cols_(rhs.cols_)
   {
      allocate();
      for (size_t i = 0; i < rows_; ++i)
      {
         memcpy(array_[i], rhs.array_[i], cols_ * sizeof(double));
      }
   }
   Matrix& operator = (const Matrix& rhs)
   {
      if (this == &rhs)
      {
         return *this;
      }
      Matrix tmp(rhs);
      swap(tmp);
      return *this;
   }
   ~Matrix()
   {
      deallocate();
   }
   double* operator [] (size_t idx)
   {
      return array_[idx];
   }
private:
   void swap(Matrix& rhs)
   {
      std::swap(rows_, rhs.rows_);
      std::swap(cols_, rhs.cols_);
      std::swap(array_, rhs.array_);
   }
   void allocate()
   {
      array_ = new double*[rows_];
      for (size_t i = 0; i < rows_; ++i)
      {
         array_[i] = new double[cols_];
         memset(array_[i], 0, cols_ * sizeof(double));
      }
   }
   void deallocate()
   {
      for (size_t i = 0; i < rows_; ++i)
      {
         delete[] array_[i];
      }
      delete[] array_;
   }
   size_t rows_, cols_;
   double** array_;
};
Вот оператор >> станет чуть сложнее просто потому что реаллокация будет происходить в НЕМ, во временные локальные массивы.
1
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
05.04.2013, 13:06  [ТС] 18
ForEveR, матрица проивзольная, не только квадратная, хотя не понимаю какое это имеет значение. В общем работает мой велосипед так - сначала проверяется корректность вводимых данных, потом текущая матрица стирается, и в нее же записываются новые значения попутно создаваясь, без временной матрицы таким образом. Через несколько часов пойду на просеминар, спрошу у того кто это задание делал как именно система тестирования будет проверять утечки, меня посетила мысль - раз от меня требуется только класс, значит пусть на уровне класса все работает без утечек, а если система тестирования сама не хочет освобождать память под объекты которые она создает, то это не мои проблемы...

Добавлено через 2 минуты
Цитата Сообщение от ForEveR Посмотреть сообщение
Вот оператор >> станет чуть сложнее просто потому что реаллокация будет происходить в НЕМ, во временные локальные массивы.
Все мои эксперименты со временными локальными массивами, заканчивались тем, что при попытке возврата значения, либо все работало но оставались утечки, либо к моменту обращения к чему либо из main память там была уже свободна - segfault

Добавлено через 3 минуты
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Matrix(const Matrix& rhs) : rows_(rhs.rows_), cols_(rhs.cols_)
   {
      allocate();
      for (size_t i = 0; i < rows_; ++i)
      {
         memcpy(array_[i], rhs.array_[i], cols_ * sizeof(double));
      }
   }
   Matrix& operator = (const Matrix& rhs)
   {
      if (this == &rhs)
      {
         return *this;
      }
      Matrix tmp(rhs);
      swap(tmp);
      return *this;
   }
Поправьте но:

C++
1
2
3
Cmatrix a,b;
...
a=b;
и
C++
1
cmatrix d=b;
это не эквивалентно ли:
C++
1
2
3
4
5
//1
a=cmatrix(b);
 
//2
d=cmatrix(b);
?

Добавлено через 3 минуты
Да и в задании странная вещь написана:
"оператор = реализуйте только в том случае, если автоматически сгенерированый компилятором вам не подходит" - делаем вывод, что есть ситуация, когда хватает автоматически сгенерированого оператора =, что я о нем знаю - так это то, что без указания конструктора он делает мелкую копию, т.е просто указатель копирует, в моем же случае, будет выполнена глубокая копия согласно конструтору. Или я ошибаюсь?
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
05.04.2013, 13:09 19
awpe, Вопрос абсолютно не понятен.
1) Вызов оператора присваивания.
2) Вызов конструктор копирования.
Дефолтный оператор = просто делает memberwise-copy. Указатель будет просто скопирован.
В вашем случае нужна глубокая копия (ну не CoW матрица же).
0
2 / 2 / 1
Регистрация: 23.11.2011
Сообщений: 87
05.04.2013, 13:15  [ТС] 20
Да, действительнр нужен = для моего случая... Тогда в каких случа он не нужен?
0
05.04.2013, 13:15
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.04.2013, 13:15
Помогаю со студенческими работами здесь

Удаление экземпляра класса в функции самого класса (Ошибка при отладке)
Допустим, у нас есть класс Buffer, который хранит в себе указатель на класс некоторой матрицы и...

Конструктор внутри класса, поля которого являются членами другого класса
Вот фрагмент кода. class Class_Figure { Class_Triangle tr1; Class_Circle cr1; public:...

Создать объект внутри класса, который может вызывать функцию этого класса
Ребята помогите уже несколько дней мучаюсь. Хочу сделать программу в консоле демонстрации работы...

Наследование: Как мне определить любой из методов заданного класса внутри другого класса?
Добрый день, подскажите пожалуйста, что я делаю не так Есть файл Container.h в котором храню...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru