void PrintArray()
{
int a[4] = {4,3,1,5};
for(int i=0; i<4; i++)
cout<<a[i];
}
在此函数的调用完成后,分配给指针变量'a'的内存和'a'指向的4整数块究竟发生了什么? 块和指针变量的内存是否被取消分配或是否会产生某种内存泄漏?
答案 0 :(得分:3)
a
不是静态变量,而是automatic
变量,来自draft C99 standard部分6.2.4
对象的存储持续时间第4段表示:
声明标识符的对象,没有链接且没有存储类 说明符静态具有自动存储持续时间。
在第3段中,它描述了static
作为程序生命周期的生命周期,第5段表示:
对于没有可变长度数组类型的对象,其生命周期会延长 从进入与之关联的块直到该块的执行结束 无论如何。 [...]
因此换句话说,对于自动变量,它的生命周期延伸到它的范围,在这种情况下,a
的范围是函数PrintArray
,并且在退出该范围后释放与其关联的存储。
对于C ++,draft standard的相关部分为3.7.3
自动存储时长第1段表示:
显式声明寄存器或未显式声明为static或extern的块范围变量具有自动存储持续时间。这些实体的存储将持续到创建它们的块退出。
答案 1 :(得分:2)
自动变量不是静态的,它们在其范围的末尾被处理掉(在函数的末尾)。静态变量将保持不变,它将保持其值,即使它在函数中被调用。以下是有关extern/static variables的链接以获取更多详细信息。
答案 2 :(得分:1)
内存不会泄漏。它没有在堆上分配。现在,这里可能涉及2个不同的内存位置。
{ 4,3,1,5 }
初始值设定项的位置。通常,像这样的初始化程序存储在数据段中。在嵌入式系统中,这可能是只读闪存。在PC或其他任何东西上,这只是一个用您的程序映像(例如EXE)初始化的RAM区域,并且不会被修改。函数退出后,它仍然存在。但它不是泄漏 - 只是程序内存占用的一部分(有些人可能会说静态内存)。a[]
函数范围内为PrintArray()
分配的堆栈内存。编译器所做的是分配一些堆栈空间,然后从数据段复制函数开头的值。这通常是发生的事情,因此如果您修改a[]
中的任何元素,它只会影响该特定函数调用的数组。再次调用PrintArray()
时,原始初始化程序未经修改且可供重用。如果后续调用PrintArray()
初始化为{ 4,3,1,5 }
以外的某些内容,由于先前的调用会使值发生变化,那将会很奇怪/意外。但是,你不是在这里修改它,所以优化可能没有在堆栈上分配任何东西是合理的。因人而异。假设a[]
确实驻留在堆栈上,它将在函数退出时自动释放(因此auto
变量)。当然,完全正在发生的事情取决于您的编译器,链接器,设置(尤其是优化)和目标。
答案 3 :(得分:0)
在C中,像a
这样的自动对象在声明它的块的出口处被丢弃。
答案 4 :(得分:0)
指针变量'a'和'a'指向的4整数块
首先,我们需要在这里找出一个基本的误解。 a
不是一个与4元素数组不同的单独指针变量; a
是 4元素数组。 a
的地址和a[0]
的地址是相同的。在大多数情况下,表达式 a
将从“{4}元素int
数组”转换为“指向int
”,并且表达式的值是数组中第一个元素的地址。
要回答这个问题,因为a
是在一个块中声明的而没有static
关键字,所以它有自动存储持续时间,这意味着数组所占用的内存离开封闭范围时释放(在本例中为函数体)。