0

我一直在自学 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”。现在变量“结果”的内存地址是否仍然被分配和/或锁定?那么参数“a”和“b”呢?

4

6 回答 6

5

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

但是自动变量(“堆栈”变量)在其作用域结束时被清理,如果/必要时调用析构函数。(您示例中的所有变量都是自动的。)

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

于 2012-02-09T06:49:24.520 回答
2

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

于 2012-02-09T06:48:22.623 回答
2

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

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

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

那么内存result仍然被分配,“锁定”并丢失。另见http://en.wikipedia.org/wiki/Call_stackhttp://en.wikipedia.org/wiki/Dynamic_memory_allocation#Dynamic_memory_allocation

于 2012-02-09T06:49:44.990 回答
1

实际上,C++ 是一个很好的资源管理器!它不对堆上分配的对象进行垃圾收集。合理地,您没有在堆上分配任何东西,并且在许多情况下,当您这样做时,您可能没有明确地这样做(例如,在使用时std::vector<T>)。要获得由其他语言中的垃圾收集处理的资源泄漏是使用在堆上分配的对象new:您需要将每个内存分配(实际上是任何资源分配)与相应的释放配对。使用std::vector<T>std::shared_ptr<T>处理 C++ 中的大量资源泄漏之类的东西。

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

于 2012-02-09T06:48:50.760 回答
1

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

对于在 C++ 中的自由存储上管理的对象,程序员有责任负责分配和解除分配……在其他语言中,这是自动的。在 C++ 中,您还需要注意基于堆栈的对象的生命周期是绑定到范围的(例如,存储或返回局部变量的地址是一个常见错误,是许多错误的起源),而这也不是问题在其他语言中。

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

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

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

于 2012-02-09T07:00:24.503 回答
0

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

范围内的对象具有由该范围分隔的生命周期,在您的示例中,result在 内部构造multiply,然后将 的副本result返回到main,然后再次将其复制到resultin main 中。

在 , 的作用域结束时multiplyresult被销毁,并且持有它的内存result被释放。

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

于 2012-02-09T06:48:27.953 回答