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

Confused about C++ memory deallocation

本文关键字:释放 c++ 内存      更新时间:2023-10-16

所以在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上调用delete。_segmentPointer,但是我如何确保内存被释放为另一个?

然而,我如何确保内存被释放给另一个?

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

当程序控制离开分配对象的作用域时,对象生命周期结束。

未分配new, new[]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()"answers"~C()"将永远不会打印。同样地,如果c_是分配给new的指针,那么它需要是delete 'd才能输出"~C()"。"

内存。_segmentObject是包含对象的内存的一部分,当包含对象被销毁时,它将被释放。

。_segmentObject是从一个临时对象分配的,该对象是在堆栈上创建的,当它超出作用域时被删除。

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

所有类类型成员对象的析构函数都在主类析构时调用。因此,在堆栈上分配的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

因此,您可以看到,当在堆栈上分配的bmain末尾超出作用域时,调用类B的析构函数,在执行析构函数体之后,调用其任何类类型成员数据对象的析构函数,在这种情况下,这将意味着类A的析构函数。因此,在您的示例中,指针将在this类的析构函数中调用delete,然后在this的析构函数完成其析构函数体的执行之后调用_segmentObject的析构函数。然后,一旦调用了非静态数据成员对象的所有析构函数,this的析构函数就会返回。

_segmentObject是在堆栈上自动分配的。当变量超出作用域时,对象析构函数将被自动调用。

正如其他人所说,您不需要显式地做任何事情来回收this._segmentObject使用的内存。一旦超出作用域,内存就会被回收。

不清楚为什么你会在两种方式中使用Segment。您应该尝试确保使用资源获取是初始化的习惯用法,因为它消除了检查new/delete对的大部分需要。也就是说,只使用this._segmentObject版本,而不使用指针。