C++中的动态数组声明

dynamic array declaration in c++

我见过两种在 C++ 中声明动态数组的方法。一种是使用 new 运算符:

int *arr = new int [size];

等是直接声明:

int arr[size];

注意:这里注意大小是一个变量,其值将由用户在运行时提供。 问题是在 C++ 中声明动态数组的最佳方法是什么?

假设您的问题是,"what is better?"。

第二种,直接创建数组,在栈上创建数组,第一种在堆上。第二个称为 variadic-length-array (VLA),它是非标准 C++ 且不可移植,但在 C 中它是标准的。 GNU C++ 编译器支持,但其他编译器不支持。在内部,数组的分配与 alloca(POSIX)/__builtin_alloca(GNU) 一样,它扩展了栈帧。 variadic-length-array 可以 粉碎 你的大堆栈(可能会产生一个 SIGSEGV,但也可能会破坏其他数据),而 new-operator 会抛出一个可捕获的异常。 (但是,使用递归函数可以 smash 你的堆栈以​​同样的方式......)。当您知道大小相对较小时,使用 VLA 并不是一个坏习惯。当数组需要多次分配时(VLA 的分配比堆上的分配更快),VLA 甚至可以提高性能。因为堆栈上的 VLA living 不需要是 freed/deleted,当函数退出时它会自动释放。 这适用于 GNU-Compilers:VLA 会在销毁时调用析构函数,但是使用 alloca/__builtin_alloca 分配的内存将在函数结束时作为内存(分配malloc) 释放 free.

作为结论,我认为 new 的分配对于大多数问题来说更好。但是 VLA 有利于在函数中进行局部快速内存分配。没有从函数 return VLA 的可移植方法(无需通过汇编进行破解)(您可以从函数 return 具有恒定大小的数组,但是需要在签名中指定)。为此,有 std::arraystd::vector,我建议使用它而不是手工制作的内存管理(分配 newdelete 或 Cs mallocfree),它在引发异常时不会被释放。如果您需要使用此类函数,Memory-management 应始终嵌套在 class 的构造函数和析构函数中。当对象超出范围时,总是会调用析构函数,因此没有内存泄漏。

VLA 和 new/delete 不能做的一件事是快速调整大小。甚至 std::vector 也不使用它。这是通过 C-function realloc 完成的,它试图将缓冲区保持在原位。当你需要这个时,你可以轻松地设计一个 std::vector-like class,它应该在析构函数中调用 free。要销毁调用 element.~T() 的元素,其中 Telement.

的类型

但是 std::vector 试图通过分配一个缓冲区来提高调整大小的性能 space。

这两种方法的主要区别在于第一种方法从Free-store(堆)分配内存,第二种方法从堆栈分配。事实上,第二个不好用,因为与堆相比,堆栈内存在 space 中非常有限。同样,第一个语句显然 returns 指向分配内存中第一个元素的指针,而第二个 returns 数组本身。