Я встречаюсь со следующей ошибкой.
Foo
. Экземпляры этого класса хранятся в станд.:: вектор vec
из class B
.new
и удаление того объекта в ~Foo()
. компиляции кода, но я получаю катастрофический отказ во времени выполнения. Если я отключаю delete my_a
от деструктора класса Foo
. Код хорошо работает (но там будет утечкой памяти).
Кто-то мог объяснить, что идет не так, как надо здесь, и предложите фиксацию?
спасибо!
class A{
public:
A(int val);
~A(){};
int val_a;
};
A::A(int val){
val_a = val;
};
class Foo {
public:
Foo();
~Foo();
void createA();
A* my_a;
};
Foo::Foo(){
createA();
};
void Foo::createA(){
my_a = new A(20);
};
Foo::~Foo(){
delete my_a;
};
class B {
public:
vector<Foo> vec;
void createFoo();
B(){};
~B(){};
};
void B::createFoo(){
vec.push_back(Foo());
};
int main(){
B b;
int i =0;
for (i = 0; i < 5; i ++){
std::cout<<"\n creating Foo";
b.createFoo();
std::cout<<"\n Foo created";
}
std::cout<<"\nDone with Foo creation";
std::cout << "\nPress RETURN to continue...";
std::cin.get();
return 0;
}
Вам необходимо реализовать конструктор копирования и оператор присваивания для Foo. Когда вы обнаружите, что вам нужен деструктор, вам наверняка понадобятся и эти два. Они используются во многих местах, особенно для помещения объектов в контейнеры стандартной библиотеки.
Конструктор копирования должен выглядеть так:
Foo :: Foo( const Foo & f ) : my_a( new A( * f.my_a ) ) {
}
и оператор присваивания:
Foo & Foo :: operator=( const Foo & f ) {
delete my_a;
my_a = new A( * f.my_a );
return * this;
}
Или, что еще лучше, не создавайте экземпляр A в классе Foo динамически:
class Foo {
public:
Foo();
~Foo();
void createA();
A my_a;
};
Foo::Foo() : my_a( 20 ) {
};
Если вы не укажете конструктор копирования, компилятор сделает его за вас.Конструктор копирования, созданный вашим компилятором, выглядит так:
Foo::Foo(const Foo& copy)
: my_a(copy.my_a)
{}
Уупс! Вы копируете только указатель, но не указанную память. Как ваш временный Foo ()
в createFoo ()
, так и тот, который скопирован в вектор, указывают на одну и ту же память, поэтому память удаляется дважды, что приводит к сбою вашей программы во второй удалять.
Вы должны создать конструктор копирования, который выглядит примерно так:
Foo::Foo(const Foo& copy)
: my_a(new A(*copy.my_a))
{}
Обратите внимание, что этот сбой происходит, если copy
имеет NULL my_a
член, и он также вызывает конструктор копирования для A
, который вы тоже не указали. Итак, вы захотите внести некоторые дальнейшие изменения. Вам также понадобится перегрузка operator =
.
Объект Foo копируется, и при уничтожении каждой копии для того же значения указателя my_a вызывается удаление. Реализуйте копию и оператор присваивания для Foo или используйте умный указатель.
Foo( const Foo& s) : my_a( s.my_a ? new A(*s.my_a) : 0) {
}
Foo& operator= (const Foo& s) {
Foo temp(s);
temp.swap (*this);
return *this;
}
void swap (Foo &s) {
std::swap (my_a, s.my_a);
};