C++释放结构使用的所有内存

C++ free all memory used by struct

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

快速问题;我已经用谷歌搜索并找到了一些答案,但我有点偏执,所以我想确定一下。

请考虑以下情况:

struct CoordLocation
{
    float X;
    float Y;
    float Z;
};
int main()
{
    CoordLocation *coord = new CoordLocation();
    delete coord;
    return 0;
}

调用 delete 是否也会清除字段 X、Y、Z 使用的内存?我找到的一些答案提到我只会删除指针,而不是以这种方式删除实际引用的对象。如果。。。

struct CoordLocation
{
    float *X;
    float *Y;
    float *Z;
};
int main()
{
    CoordLocation *coord = new CoordLocation();
    delete coord;
    return 0;
}

如果我手动释放结构构造函数/析构函数内每个对象的内存怎么办?

struct CoordLocation
{
    CoordLocation()
    {
         *X = new float;
         *Y = new float;
         *Z = new float;
    }
    ~CoordLocation()
    {
         delete X; delete Y; delete Z;
    }
    float *X;
    float *Y;
    float *Z;
};
int main()
{
    CoordLocation *coord = new CoordLocation();
    delete coord;
    return 0;
}

我注意到对于一个简单的情况,例如:

   float *a = new float;
   *a = 5.0f;
   printf("%f", *a);
   delete a;
   printf("%f", &a);

printf 将打印 5.0,因此 a 指向的变量不会完全被破坏。

所以我的问题是:在这种情况下,我如何可靠地释放(如没有内存泄漏)结构体使用的所有内存?

struct CoordLocation
{
    float X;
    float Y;
    float Z;
};
int main()
{
    CoordLocation *coord = new CoordLocation();
    delete coord;
    return 0;
}

谢谢!

您只需要delete使用 new 分配的内存。

printf 将打印 5.0,因此 a 指向的变量不会完全被破坏。

您实际上遇到了未定义的行为。尽管该值仍然存在,但内存已释放并可以重用。

所以以下内容:

struct CoordLocation
{
    float X;
    float Y;
    float Z;
};

如果省略析构函数,则无法创建内存泄漏。

您的下一个代码段:

struct CoordLocation
{
    float *X;
    float *Y;
    float *Z;
};
int main()
{
    CoordLocation *coord = new CoordLocation();
    delete coord;
    return 0;
}

可能会造成内存泄漏,但事实并非如此。以下内容将:

int main()
{
    CoordLocation *coord = new CoordLocation();
    coord->X = new float();
    delete coord;
    return 0;
}

你的第三个例子

struct CoordLocation
{
    CoordLocation()
    {
         *X = new float;
         *Y = new float;
         *Z = new float;
    }
    ~CoordLocation()
    {
         delete X; delete Y; delete Z;
    }
    float *X;
    float *Y;
    float *Z;
};
int main()
{
    CoordLocation *coord = new CoordLocation();
    delete coord;
    return 0;
}

不会创建内存泄漏,因为您可以释放分配的所有内存。如果你要省略析构函数或忘记调用delete coord;,它们就会有内存泄漏。

一个好的经验法则:为每new打电话delete,为每new[]打电话delete[],您就安全了。

在此示例中:

struct CoordLocation
{
    float X;
    float Y;
    float Z;
};
int main()
{
    CoordLocation *coord = new CoordLocation();
    delete coord;
    return 0;
}

内存被释放。该代码中没有泄漏。在您给出的示例中,您的结构包含指针,只要您在析构函数中释放它们(就像您在示例中所做的那样),就不会有泄漏。

在此代码段中:

float *a = new float;
*a = 5.0f;
printf("%f", *a);
delete a;
printf("%f", &a);

删除后,a的值保持不变,因为指针delete只会将内存地址标记为"释放",因此它不会修改其内容。访问释放的指针是未定义的行为。

指针本身分配了自动存储持续时间,那里没有什么可以释放的。结构是这三个字段,当您调用 delete 时会释放它们。您只对new返回的内容调用delete

当您分配某些内容时,您会分配足够的内存来保存它,这意味着有足够的内存来保存其所有字段(以及一些特定于实现的内务内存,但您不必担心这一点)。删除它时,将释放与分配的内存量相同的内存量。

但是,需要注意的一件事是这样的情况(C++您不会创建这样的类型,但该示例是相关的):

struct Foo {
    char *str;
};
Foo *f = new Foo();
f->str = new char[10];
delete f;

在这种情况下,您有泄漏。 你删除了f,它包含足够的内存来容纳单个char*,但char*指向的内容也是动态分配的。 因此,您还需要释放它:

delete f->str;
delete f;

同样,在C++中,您可能不会以这种方式设计类型,而是偏爱像std::string这样的类型和像 RAII 这样的原则,但该示例是相关的。