связанный с вектором вопрос о выделении памяти

Я встречаюсь со следующей ошибкой.

  • У меня есть класс Foo . Экземпляры этого класса хранятся в станд.:: вектор vec из class B.
  • в классе Нечто я создаю экземпляр класса A путем выделения использования памяти 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;
}
5
задан memC 27 April 2010 в 09:17
поделиться

3 ответа

Вам необходимо реализовать конструктор копирования и оператор присваивания для 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 ) {
};
7
ответ дан 13 December 2019 в 05:32
поделиться

Если вы не укажете конструктор копирования, компилятор сделает его за вас.Конструктор копирования, созданный вашим компилятором, выглядит так:

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 = .

3
ответ дан 13 December 2019 в 05:32
поделиться

Объект 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);  
 }; 
2
ответ дан 13 December 2019 в 05:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: