5

我遇到以下错误。

  • 我有一堂课Foo。此类的实例存储在 std::vectorvecclass B
  • 在 Foo 类中,我通过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;
}
4

3 回答 3

7

您需要为 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;
}

或者更好的是,不要在 Foo 类中动态创建 A 实例:

class Foo {      
      public:
             Foo();
             ~Foo();
             void createA();
             A my_a;
};

Foo::Foo() : my_a( 20 ) {
};
于 2010-04-27T09:20:28.550 回答
3

如果您不指定复制构造函数,编译器会为您创建一个。您的编译器生成的复制构造函数如下所示:

Foo::Foo(const Foo& copy)
    : my_a(copy.my_a)
{}

哎呀!您只复制指针而不是指向的内存。您的临时Foo()increateFoo()和复制到向量的一个都指向同一内存,因此该内存被删除两次,这会使您的程序在第二次删除时崩溃。

您应该创建一个看起来像这样的复制构造函数:

Foo::Foo(const Foo& copy)
    : my_a(new A(*copy.my_a))
{}

请注意,如果copy有一个 NULLmy_a成员,它会崩溃,并且它还会调用A您尚未指定的复制构造函数。所以你会想要做一些进一步的改变。你也需要operator=超载。

于 2010-04-27T09:31:13.430 回答
2

Foo 对象被复制,并且在每个副本的销毁时,在相同的指针值 my_a 上调用 delete。为 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);  
 }; 
于 2010-04-27T09:25:51.390 回答