Создаю класс для работы со множествами, для расчет кол-ва тиков clock() прогоняю одну и ту же операцию N (const) раз. В итоге происходит огромная утечка памяти. Возможно дело в том, что в бинарных операциях & и | я создаю новый экземпляр класса с помощью дин. памяти каждую итерацию цикла. Но как освободить динамическую память в таком случае?
#include "stdafx.h"
#include
const unsigned int N = 100000;
//Массив символов
class Set {
int n; //Мощность множества
static int U; //Мощность универсума
char litera; //Обозначение множества A,B,C,D и так далее
char* universe; //Указатель на множество
public:
Set(char _litera);
~Set();
Set();
void print();
int power() { return n; }
//Операции над множествами
Set& operator & (const Set& B) const;
Set& operator ~ () const;
//Операторы копирования и присваивания с переносом
Set(Set &);
Set& operator = (Set& B);
};
Set::Set() : litera('0'), n(0), universe(new char[U + 1]) {
//cout << "Создание пустого множества " << litera << " = []
";
universe[0] = '\0';
};
Set ::~Set() {
//cout << "Удаление множества " << litera << '
';
delete[] universe;
}
Set:: Set(char _litera): litera(_litera),n(0),universe(new char[U+1]) {
for (int i = 0; i < U; i++) {
if (rand() % 2) {
universe[n++] = '0' + i;
}
}
universe[n] = '\0';
//cout << "Создание множества " << litera << " = [" << universe << "]
";
}
void Set::print() {
cout << litera << " = [" << universe << "]" << '
';
}
//Операции над множествами
Set& Set:: operator & (const Set& B) const {
Set *C = new Set;
for (int i = 0; i < n; i++) {
for (int j = 0; j < B.n; j++) {
if (universe[i] == B.universe[j]) C->universe[C->n++] = universe[i];
}
}
C->universe[C->n] = 0;
//cout << "Результат пересечения множества " << litera << " = [" << universe << "]"
// << " со множеством " << B.litera << " = [" << B.universe << "]" << " => " << C->litera << " = [" << C->universe << "]
";
return *C;
}
Set& Set:: operator ~ () const {
Set *C = new Set;
for (char ch = '0'; ch <= '9'; ch++) {
bool flag = true;
for (int j = 0; j < n; j++) {
if (ch == universe[j]) { flag = false; break; }
}
if (flag) C->universe[C->n++] = ch;
}
C->universe[C->n] = '\0';
//cout << "Результат инверсии множества " << litera << " = [" << universe << "]"
// << " => " << C->litera << " = [" << C->universe << "]
";
return *C;
}
//Операторы перегрузки и присваивания с переносом
Set:: Set(Set & B): litera(B.litera), n(B.n), universe(B.universe) {
//cout << "Конструктор копирования множества c переносом " << B.litera << '
';
B.universe = NULL;
}
Set& Set:: operator = (Set& B) {
//cout << "Конструктор присваивания множества с переносом" << B.litera << '
';
if (this != &B) {
n = B.n;
universe = B.universe;
litera = 'R';
B.universe = NULL;
}
return *this;
}
//Поместить после include
int Set::U = 10; //Мощность универсума для десятичных цифр
int main() {
setlocale(LC_ALL, "");
srand(time(NULL));
time_t start, stop;
Set A('A'), B('B'), C('C'), D('D'), E;
A.print();
B.print();
C.print();
D.print();
system("pause");
//Обработка множеств
start = clock();
for (int i = 0; i < N; i++) E = ((A & ~(B & C)) & ~D);
stop = clock();
//Вывод итогового множества
E.print();
//Вывод средней мощности и времени
cout << "Average power = " <<
(A.power() + B.power() + C.power() + D.power() + E.power()) / 5 << '
';
cout << "Time = " << stop - start << '/' << N << '
';
system("pause");
return 0;
}
Ответ
У Вас в "операторах" ~ и & выделяется динамическая память:
Set& Set:: operator ~ () const {
Set *C = new Set;
Но она нигде не освобождается.
Сразу возникает вопрос, а зачем Вам понадобилась здесь динамическое выделение памяти?
Может всё-таки переделать без динамической памяти?
Set Set:: operator & (const Set& B) const {
Set C;
//работа с C
return C;
}
Set Set:: operator ~ () const {
Set C;
//работа с C
return C;
}
(объявления тоже необходимо переделать под новые условия).
Во-первых, избавились от динамической аллокации,
во-вторых, нормальный компилятор применит NRVO,
устранив, тем самым, копирование в возвращаемое значение.
Также стоит учесть, что Ваши operator= и конструктор копирования повторяют печальную судьбу auto_ptr, когда присваивание и копирование захватывает ресурсы исходного объекта. Стоило бы сделать дополнительно перемещающие версии, предоставив пользователю больше средств.
Комментариев нет:
Отправить комментарий