C++内存乱码

C++ memory garbaging

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

我一直在自学C++,有人告诉我C++没有垃圾收集器。现在我不确定这意味着什么。

假设我有这个代码:

double multiply (double a, double b) {
    double result = a * b;
    return result;
};
int main (char* args[]) {
    double num1 = 3;
    double num2 = 12;
    double result = multiply(num1, num2);
    return 0;
}

multiply方法包含一个内部变量"result"。现在,变量"result"的内存地址是否仍被分配和/或锁定?参数"a"&"b"?

标准C++根本没有垃圾收集器。

但是,当自动变量("堆栈"变量)的作用域结束时,它们会被清除,必要时会调用析构函数。(示例中的所有变量都是自动的。)

您需要担心的是动态分配:通过new运算符创建的任何内容。这些不是自动清理的-你需要delete它们,否则它们会泄漏。(或者使用智能指针。)

您提到的所有变量都在堆栈中。一旦它们超出范围,内存就会自动释放。

垃圾回收意味着您的垃圾(上不可访问/引用的内存)将自动释放。本地内存/变量(本地变量)不会被分配,而是被推送到堆栈上,如果您离开定义变量的块,则会自动释放。

所以,如果你使用你的代码,你就可以了。但是如果你使用

double multiply (double a, double b) {
    double *result = new double;
    *result = a * b;
    return *result;
};

result中的存储器仍然被分配、"锁定"和丢失。另请参阅http://en.wikipedia.org/wiki/Call_stack和http://en.wikipedia.org/wiki/Dynamic_memory_allocation#Dynamic_memory_allocation.

实际上,C++是一种非常好的资源管理!它不对堆上分配的对象进行垃圾收集。合理地说,您没有在堆上分配任何内容,而且在许多情况下,当您这样做时,您可能没有显式地这样做(例如,当使用std::vector<T>时)。在其他语言中,垃圾收集处理的资源泄漏是使用new在堆上分配的对象:您需要将每个内存分配(实际上是任何资源分配)与相应的发布配对。使用像std::vector<T>std::shared_ptr<T>这样的东西可以处理C++中大量的资源泄漏。

也就是说,您的示例程序并没有资源泄漏。

C++有两种主要类型的内存,用于分配对象:堆栈和空闲存储(堆)。堆栈上的对象是手动分配和释放的,其中包括函数参数、自动(本地)变量、临时对象和返回值。空闲存储(堆)上的对象由newnew[]deletedelete[]显式管理。您还可以使用malloc/free或使用命名奇特的函数operator newoperator delete及其对应的[]来管理空闲存储中的原始内存。

对于在C++中的免费存储中管理的对象,程序员有责任负责分配和释放。。。在其他语言中,这是自动的。在C++中,您还需要注意,基于堆栈的对象的生存期与作用域绑定(例如,存储或返回局部变量的地址是一个常见的错误,或者是许多错误),而这在其他语言中也是没有问题的。

这种复杂性的主要原因是速度:使用基于堆栈的分配逻辑比使用自由存储要快得多(当前处理器在堆栈上分配许多变量只需要一个加法,而解除分配则只需要减法)。

对于其他语言,编译器会分析代码,并决定在哪里可以使用堆栈分配,在哪里不能使用堆栈分配。相反,在C++中,这是程序员的工作。

注意,在C++中,内存管理实际上比这个解释更复杂(例如,还有存储异常对象的内存,可以为类提供自定义分配器,还有容器的分配器参数),但程序员很少需要考虑它

C++没有垃圾收集器是事实(大多数情况下,忽略外部库)。相反,它具有自动存储持续时间的概念。

作用域内的对象的生存期由该作用域限定,在您的示例中,resultmultiply中构造,然后result的副本返回到main,在那里它再次被复制到主中的result中。

multiply作用域的末尾,result被破坏,并且保持它的存储器result被释放。

这种"自动内存管理"不使用垃圾收集器,而且完全是确定性的。