返回新分配的数组

Return newly allocated array

本文关键字:数组 分配 新分配 返回      更新时间:2023-10-16

在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
    }
}

allocateArrayallocateArrayVar之间有什么区别吗?为什么allocateArrayVar有效而doubleValue()无效?

这两个函数之间没有区别。

然而,代码中的注释有点误导:

我原以为var的内存会在这里被释放

使用new的目的是,一旦内存超出范围,就不会释放内存。虽然var是"解除分配"的,但指向的数据(即*var)并不是解除分配的。

在这种情况下,程序员需要手动解除分配使用new分配的内存。这就是你可以做到的:

void dellocateArray(int* arr) {
  delete[] arr;
}

allocateArrayVar工作但doubleValue不工作的原因来自于谁管理内存之间的区别:

  • 当用new(或malloc等)分配某个东西时,它会在上创建,并因此进行分配,直到程序员用delete(或free等)解除分配。

  • 所有其他实例化都是在堆栈上完成的,一旦超出范围,就会被释放。因为内存可以回收,所以不能保证该内存地址会包含您所期望的内容。

allocateArrayallocateArrayVar之间没有差异。doubleValue返回一个指向局部变量的指针,当函数返回(即超出范围)时,该变量将被销毁,因此指针变为无效。然而,当您使用new运算符时,您正在堆上分配内存,这最终意味着内存在您对其调用delete之前保持有效(您确实应该这样做以避免内存泄漏)。

您的困惑源于您对"局部变量"的定义。

当您编写以下代码时:

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

其中int value分配在堆栈上。函数调用完成后,堆栈内存确实会被释放,因此这里的返回值是无效的(它指的是堆栈上的内存地址,而不是堆)。

首先,在结果的情况下,allocateArrayallocateArrayVar之间没有差异。如果您想知道程序的工作方式是否存在差异,请尝试在不进行优化的情况下,使用生成汇编代码的选项,先使用第一个函数,然后使用第二个函数编译版本。并进行比较;)

如果使用new运算符,操作系统将在所谓的堆上分配内存,该堆不属于任何函数。只有一种方法可以解除分配此类内存:使用delete运算符。

关于返回引用,返回对局部变量的引用是个坏主意(行不通),因为当函数终止时,局部变量会超出范围。

在这种情况下,最好返回对象(包括指针),因为使用new分配的内存存储在堆存储中,只要使用delete运算符手动删除,堆存储就有其生存期。

参考:C++初级读本。很喜欢那本书:)