为什么在分配时,下面的C ++中没有memleaks?

时间:2011-12-08 06:42:21

标签: c++ memory-leaks

以下代码降低了我的信念,即我或多或少地了解C ++。为什么valgrind在这里没有显示任何memleak?为什么我期待memleaks:

  1. B大于A:它包含一个额外的成员;所以在分配时应该有类'fields slicing。
  2. ~A()没有虚拟dtor。因此,当我们调用delete a时,只应调用~A()并且B中分配的内存将丢失。
  3. 但我收到dtors的调用顺序是:~A(),~B(),~A()。为什么呢?!

    struct A {
      ~A()
      {
          std::cerr << "~A" << std::endl;
      }
    };
    
    struct B : A {
      int* data;
    
      B() : data(new int[20]) {}
    
      ~B()
      {
        std::cerr << "~B" << std::endl;
        delete [] data;
      }
    };
    

    main()

    A* a = new A;
    B* b = new B;
    *a = *b;
    
    delete a;
    delete b;
    

    UPD: 对我感到羞耻!当虚拟dtor应该被调用时,我混淆了基类指针删除对象。这里只是课堂复制的内容。谢谢大家!

7 个答案:

答案 0 :(得分:5)

delete a;

aA*,因此A::~A被称为

delete b;

bB*,因此B::~B被调用。

为什么会出现问题?

类字段的切片?所以啊?您只是将A字段从*b复制到*a,仅此而已。这里没有记忆丢失。

答案 1 :(得分:1)

*a = *b中,您正在*b复制(是的,切片)到*a。但是,这使*b保持不变;它没有切片。当您delete b时,您要求~B()调用*b

答案 2 :(得分:1)

*a = *b;作业仅复制数据的常见A部分(A没有字段)。

答案 3 :(得分:0)

你删除了每个新内容,所以没有memleak。

*a =*b

没有分配任何东西,复制构造函数只是复制b的一部分可以转到a,但它不会调用new ..

答案 4 :(得分:0)

通过调用*a = *b;,您隐式调用编译器创建的赋值运算符函数,如下所示:

A &operator=( const A &other ){
}

在你的情况下没有做任何事情,因为A没有成员变量。

答案 5 :(得分:0)

您的班级A是空的,因此与本次讨论的目的完全无关。动态分配中涉及的唯一代码是:

B* b = new B;
delete b;

由于您delete使用new创建了一个对象,因此没有泄漏。此外,类B包含足够的代码来清理其在这个直接用例中的内部分配。

(请注意,class B仍然可怕地被打破,因为它无法在复制或分配中存活。经典的三法则(或五)。)

答案 6 :(得分:0)

因为你在这里做的是对象切片。我认为您打算让基指针指向派生对象,并且由于基本析构函数不是虚拟的,因此在清理期间不会调用派生类析构函数。但这不是这种情况。

*a = *b 

编译器将“切片”对象的派生部分,并仅复制对象的基本部分。这通常不是我们想要做的,因为这会导致一个不完整的对象,只有基类属性和缺少专门的派生类属性。