对C ++内存释放感到困惑

时间:2011-07-20 18:55:39

标签: c++ memory-management

所以在C ++中如果我创建一个使用new的对象,我应该总是使用delete解除分配。 例如

Segment::Segment(float length)
{
    segmentLength = length;

    angle = 0.0f;
    x = Rand::randFloat(1.0f, 1.5f);
    y = Rand::randFloat(1.0f, 1.5f);

    vx = Rand::randFloat(0.0f, 1.0f); 
    vy = Rand::randFloat(0.0f, 1.0f);
    prevX = Rand::randFloat(0.0f, 1.0f);
    prevX = Rand::randFloat(0.0f, 1.0f);
};

让我说我在另一个类中使用它,例如,

this._segmentObject = Segment(2.0f);
this._segmentPointer = new Segment(2.0f);

在该类的析构函数中,我知道我应该在this._segmentPointer上调用delete,但是如何确保为另一个内存释放内存?

7 个答案:

答案 0 :(得分:5)

  

但是如何确保为另一个内存释放内存?

这是自动的。这就是为什么这种类型的存储被称为自动。自动存储在存储生命周期结束时释放,对象的析构函数称为。

当程序控件离开已分配对象的范围时,对象生命周期结束。

答案 1 :(得分:4)

当对象超出范围时,未分配newnew[]malloc系列的内容应被销毁并“释放”。

这通常意味着代码已经到达它声明的块的末尾,或者它所在的对象被破坏(以这种或那种方式)。

要看到这一点,你可以这样做:

struct C {
    C()  { std::cout << "C()" << std::endl; }
    ~C() { std::cout << "~C()" << std::endl; }
};

struct B {
    B()  { std::cout << "B()" << std::endl; }
    ~B() { std::cout << "~B()" << std::endl; }
private:
    C c_;
};

struct A {
    A()  { std::cout << "A()" << std::endl; }
    ~A() { std::cout << "~A()" << std::endl; }
};

int main() {
    B *b = new B; // prints "B()", also constructs the member c_ printing "C()"
    { // starts a new block
        A a; // prints "A()";
    } // end of block and a's scope, prints "~A()"

    delete b; // prints "~B()", also destructs member c_, printing "~C()"
}

注意:如果我们没有delete b,则“~B()”和“~C()”将永远不会打印。同样,如果c_是分配有new的指针,则需要delete'才能打印“~C()”

答案 2 :(得分:3)

this._segmentObject的内存是包含对象内存的一部分,并在包含对象被销毁时释放。

this._segmentObject是从堆栈上创建的临时对象中分配的,并在超出范围时被删除。

答案 3 :(得分:1)

不仅如此,您只应在构造函数或析构函数中使用new和deallocate with delete进行分配,否则如果抛出异常,您的程序可能会泄漏。

答案 4 :(得分:1)

在销毁主类时调用所有类类型成员对象的析构函数。因此,在堆栈上分配的this对象将在超出范围时调用析构函数。那时,除了this对象的析构函数之外,this对象的任何类型成员对象都将调用自己的析构函数,这些析构函数将在成员指针上调用delete

例如,请使用以下代码示例:

#include <iostream>

using namespace std;

class A
{
        public:
                A() {}
                ~A() { cout << "Destructor for class A called" << endl; }
};

class B
{
        private:
                A a;

        public:
                B() {}
                ~B() { cout << "Destructor for class B called" << endl; }
};

int main()
{
        B b;
        return 0;
}

运行时,输出变为以下内容:

Destructor for class B called  
Destructor for class A called

所以你可以看到,当b(在堆栈上分配)超出main末尾时,会调用类B的析构函数,反过来,在执行析构函数体之后,为其任何类类型成员数据对象调用析构函数,在这种情况下,它将表示类A的析构函数。因此,在您的情况下,指针将在delete类的析构函数中调用this,然后在_segmentObject的析构函数之后调用this的析构函数已经完成了析构函数体的执行。然后,一旦调用了所有非静态数据成员对象的析构函数,this的析构函数就会返回。

答案 5 :(得分:0)

_segmentObject在堆栈上自动分配。 当变量超出范围时,将自动调用对象析构函数。

答案 6 :(得分:0)

正如其他人所说,你不需要明确地做任何事情来回收this._segmentObject使用的内存。一旦超出范围,内存将被回收。

目前尚不清楚为何会以两种方式使用Segment。您应该尝试确保使用Resource Acquisition Is Initialization惯用法,因为它消除了检查new / delete对的大部分需求。也就是说,只使用this._segmentObject版本,而不是指针。

但您的申请可能不允许这样做。