在C/C++中有没有一个函数可以去除非动态数据,类似于动态分配内存的函数free();
。
我尝试使用函数 free(i);
但编译器报错:
invalid conversion from 'int' to 'void*' [-fpermissive]
在下面的代码中我使用了free(&i);
,编译器没有报错,但是也没有释放内存。
#include<iostream>
#include<stdlib.h>
int main()
{
int i, n;
cin >> n;
for(i = 0; i < n; i++);
cout << i << endl;
free(&i);
cout << i << endl;
return 0;
}
对于输入 15
输出是:
15
15
Process returned 0 (0x0) execution time : 11.068 s
Press any key to continue.
我从编译器那里得到了警告:
warning: attempt to free a non-heap object 'i' [-Wfree-nonheap-object]
最佳答案
我将在这里为高级答案集添加一个初学者级别的答案,以防真正的新手偶然发现这个问题:
您不需要释放堆栈上的数据结构,并且 - 正如 Deduplicator 指出的那样 - 您也不允许这样做。 除了一些特殊情况外,所有非动态分配(例如通过 new)的数据由编译器放在堆栈上。堆栈是程序在运行时的内存部分,随着每次函数调用而增长,并随着每次函数退出而缩小。它分为所谓的栈帧,提供函数的本地内存。在编译时,编译器会找出一个函数需要多少内存——在您的示例中,两个 4 字节整数需要 8 个字节(假设您正在编译为 32 位目标)——并生成为所有函数创建足够大堆栈帧的指令调用函数时驻留的局部变量。但是,有一种方法可以告诉编译器您只需要在函数内的有限时间内使用一个变量:作用域,它由大括号创建 - 正如 niklasfi 指出的那样。一个例子:
int foo() {
int outerScopeVariable = 5;
{
int innerScopeVariableA = 8;
}
{
int innerScopeVariableB = 20;
}
}
变量 innerScopeVariableA
只会“存在”在它周围的花括号中。在高级别上,这意味着您不能在 {}
block 之外的范围内引用它,它已在其中声明,并且对于 block 末尾的类,将调用对象的析构函数。在低级别上,编译器知道在 block 的末尾不再需要为 innerScopeVariableA
保留的内存。因为它是堆栈内存,所以它不能像释放动态内存那样释放它。请记住,堆栈内存仅在函数结束时被丢弃。但它可以做的是为 innerScopeVariableB
重用 innerScopeVariableA
的内存。因此,对于 foo
,优化编译器实际上仅需 8 个字节的堆栈内存。
有关堆栈和堆(这是分配动态内存的地方)的更多信息,您可以查看这个问题:What and where are the stack and heap? .可以在此处找到对堆栈的深入讨论:http://www.altdevblogaday.com/2011/12/14/c-c-low-level-curriculum-part-3-the-stack/
编辑:如果将大数据结构放在堆栈上,您实际上可以观察到这种堆栈内存重用。运行以下使用 g++ 4.8.1 编译的代码,您的输出是 123987
。
#include <iostream>
using namespace std;
void foo() {
{
int a[1024];
a[0] = 123987;
}
{
int b[1024];
cout << b[0] << endl;
}
}
int main() {
foo();
return 0;
}
查看二进制 g++ 在堆栈上为 foo 保留了 4136 个字节,其中 4096 个字节对于一个具有 1024 个元素的整数数组是必需的(我已经为 32 位目标编译)。一点点额外的空间可能与内存对齐有关。您还可以通过打印内存地址来观察这种效果,这是一个使用在线编译器的示例:http://codepad.org/r5S1hvtV .
关于c++ - 在 C++ 中摆脱非动态内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23032157/