【问题标题】:Memory leak c++ pointers内存泄漏 C++ 指针
【发布时间】:2016-02-18 05:38:55
【问题描述】:
int main()
{
    A* x = new B(10, 20);
    x->opt1();
    delete x;
    return 0;
}

int main()
{
    B x(10, 20);
    return 0;
}

所以,第一个有内存泄漏,我理解是因为 x 是一个指向 B 对象的 A 对象。如果 A 不是指针,它还会有内存泄漏吗?

为什么第二个函数没有内存泄漏?我们不需要删除 x?

class A
{
    private:
        int* a;
    public:
        A(int size) {
            a = new int[size];
        }
        ~A() {
            if (a) {
                delete [] a;
            }
        };
        virtual void opt1() {
            cout << "A::opt1()" << endl;
        }
};

class B : public A
{
    private:
        float* b;
    public:
        B(int size1, int size2) : A(size1) {
            b = new float[size2];
        }
        ~B() {
            if(b){
                delete [] b;
            }
        }
        virtual void opt1() {
            cout << "B::opt1()" << endl;
        }
};

【问题讨论】:

  • A 有虚拟析构函数吗?

标签: c++ memory-leaks


【解决方案1】:

第一个有内存泄漏,我理解是因为 x 是一个指向 B 对象的 A 对象。

不,如果AB 具有明确定义的继承关系,则不会发生内存泄漏。如:

class A {
public:
    virtual ~A() {}
};

class B : public A {
};

为什么第二个函数没有内存泄漏?

因为x是在栈上分配的,不需要也不能调用deletex 会被自动销毁。

我们不需要删除x?

只有new创建的对象需要delete

编辑

对于你AB的代码,第一种情况会导致内存泄漏,因为A(基类)的析构函数不是virtual。对于

A* x = new B(10, 20);
delete x;

只有A的析构函数会被调用,B的析构函数不会被调用,也就是说B里面的float* b不会被释放。

如果你想以这种方式使用它们是个坏主意,即通过指向基类的指针删除派生类的实例。

When to use virtual destructors?

【讨论】:

  • 糟糕,抱歉,忘记包含类本身。看起来 A 有继承关系和析构函数,这就是我感到困惑的原因。
  • @Brian 因为A 的析构函数不是virtual,所以第一种情况会导致内存泄漏。请参阅我编辑的答案。
【解决方案2】:

在第二个中,new 没有被显式调用,尽管项目的构造函数是。但是变量会自动超出范围,因此自动调用析构函数可以防止任何类型的泄漏,前提是正确编写析构函数以抵消对象内的任何内部分配。

我认为第一个示例不会是内存泄漏,但可能存在导致问题的基类的一些细微之处。

【讨论】:

    猜你喜欢
    • 2013-10-31
    • 2015-12-15
    • 2014-08-25
    • 1970-01-01
    • 1970-01-01
    • 2016-05-14
    • 2019-06-18
    • 2014-09-25
    • 1970-01-01
    相关资源
    最近更新 更多