在C ++中,当函数离开其范围时,局部变量会被破坏。
int* doubleValue(int x)
{
int value = x * 2;
return &value; // return nValue by address here
} // value destroyed here
但是我尝试了以下函数,似乎函数allocateArray
的两个版本
运作良好
int* allocateArray(int size)
{
return new int[size];
}
int* allocateArrayVar(int size)
{
int* var = new int[size];
return var;
}//I expected memory for var would be deallocated here
int _tmain(int argc, _TCHAR* argv[])
{
{
int* ar1 = allocateArray(10);
ar1[0] = 1;// I can write into memory
int* ar2 = allocateArrayVar(10);
ar2[0] = 2;// I can write into memory
}
}
allocateArray
和allocateArrayVar
之间有什么区别吗?
为什么allocateArrayVar
确实有效但doubleValue()
没有?
答案 0 :(得分:4)
allocateArray
和allocateArrayVar
之间没有区别。
doubleValue
返回一个指向局部变量的指针,该函数将在函数返回时被销毁(即,它超出范围),因此指针变为无效。但是,当您使用new
运算符时,您正在堆上分配内存,这最终意味着内存保持有效,直到您在其上调用delete
(为了避免内存,您应该这样做泄漏)。
答案 1 :(得分:4)
这两个功能没有区别。
但是,您的代码中的注释有点误导:
我预计
var
的内存将在此处取消分配
使用new
的重点是,一旦超出范围,您的记忆就不会被释放。虽然var
是"已取消分配",但并不是指向的数据(即*var
)被解除分配。
程序员,在本例中你,需要手动释放使用new
分配的内存。这就是你如何做到的:
void dellocateArray(int* arr) {
delete[] arr;
}
allocateArrayVar
的作用原因,doubleValue
并非来自管理记忆的人之间的区别:
当使用new
(或malloc
等)分配某些内容时,它会在堆上创建,因此会被分配,直到程序员解除分配为止它与delete
(或free
等)。
所有其他实例化都在堆栈上完成,一旦超出范围,将被解除分配。由于可以回收内存,因此无法保证该内存地址将包含您所期望的内容。
答案 2 :(得分:3)
您的困惑源于您对"本地变量的定义"。
编写以下代码时:
SIGTERM
是的,您正在返回本地变量int* allocateArrayVar(int size)
{
int* var = new int[size];
return var;
}
的副本,但var
的值是分配数组的内存地址。当内存分配有var
时,它将存储在堆上,在您手动调用new
之前,该堆不会被释放。
因此,当delete
的调用者收到返回值时,即使allocateArrayVar
本身不再存在,它仍会获得有效的内存地址。
将此方法与
进行对比int* var
在堆栈上分配int* doubleValue(int x)
{
int value = x * 2;
return &value; // return nValue by address here
} // value destroyed here
的位置。函数调用完成后,堆栈内存会被解除分配,因此这里的返回值无效(它指的是堆栈上的内存地址,而不是堆)。
答案 3 :(得分:3)
首先,在结果的情况下,allocateArray
和allocateArrayVar
之间没有区别。如果您想知道程序的工作方式是否存在差异,请尝试先编译版本,然后使用第二个函数编译而不进行优化,并使用生成汇编代码的选项。并比较它们;)
如果您使用的是new
运算符,则操作系统会在所谓的堆上分配内存 - 这个位置不属于任何函数。
只有一种方法可以释放这种内存:使用delete
运算符。
答案 4 :(得分:1)
关于返回引用,返回对局部变量的引用是一个坏主意(不起作用),因为当函数终止时局部变量超出范围。
在这种情况下,最好返回对象(包括指针),因为使用new
分配的内存存储在堆存储中,只要使用delete
运算符手动删除它就具有生存期。
参考:C ++ Primer。只爱这本书:)