Возможный дубликат:
Что такое правило трех?
У меня есть проблема двойного освобождения памяти в следующей программе.
Отладчик показывает, что проблема в push_back()
функция.
Класс А:
class A {
public:
A(int x);
int x;
};
A::A(int x) {
this->x = x;
}
Класс Б:
class B {
public:
B(int x);
~B();
A* a;
};
B::B(int x) {
this->a = new A(x);
}
B::~B() {
delete a;
}
Основная функция:
int main() {
vector<B> vec;
for(int i = 0; i < 10; i++) {
vec.push_back(B(i)); <------------ Issue is here
}
cout << "adding complete" << endl;
for(int i = 0; i < 10; i++) {
cout << "x = " << (vec[i].a)->x << endl;
}
return 0;
}
Что не так в этом коде?
РЕДАКТИРОВАТЬ: ошибка double free or memory corruption
Все остальные уже заговорили об этом, поэтому я не буду погружаться дальше.
Чтобы рассмотреть использование, которое вы, очевидно, пытаетесь выполнить (и соответствует Правилу Трех в процессе исключения), попробуйте следующее. В то время как все абсолютно правы в отношении правильного управления владением динамическими элементами, можно легко создать конкретный образец, чтобы избежать их использования. полностью.
Класс А
class A {
public:
A(int x);
int x;
};
A::A(int x)
: x(x)
{
}
Класс б
class B {
public:
B(int x);
A a;
};
B::B(int x)
: a(x)
{
}
Основная программа
int main() {
vector<B> vec;
for(int i = 0; i < 10; i++) {
vec.push_back(B(i));
}
cout << "adding complete" << endl;
for(int i = 0; i < 10; i++) {
cout << "x = " << vec[i].a.x << endl;
}
return 0;
}
Нижняя линия
Не используйте динамическое распределение, если у вас нет веских причин, а также он защищен в течение всей жизни содержащимися переменными, такими как умные указатели или классы, которые энергично практикуют Правило Трех.
Вы забыли определить конструктор копирования и оператор присваивания, поэтому ваш обернутый объект delete
некоторые B
…. потом опять когда какая-то копия B
выходит за рамки.
В этом случае это B(i)
Временная на линии, которую вы определили, а также количество копий, определяемое реализацией в векторе.
Соблюдать правило трех.
Проблема в вашем коде связана с тем, что «простые» указатели C / C ++ не имеют понятия владение. Когда указатель копируется, обе копии* «думаю», что они владеют данными, что приводит к двойному удалению.
Признавая этот факт, разработчики стандартной библиотеки C ++ представили unique_ptr<T>
класс, который поможет вам решить такие проблемы.
* Одна копия указателя находится в случае B
перешел к push_back
; другая копия указателя находится в экземпляре, введенном в vector
,