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 不需要是 free
d/delete
d,当函数退出时它会自动释放。
这适用于 GNU-Compilers:VLA 会在销毁时调用析构函数,但是使用 alloca
/__builtin_alloca
分配的内存将在函数结束时作为内存(分配malloc
) 释放 free
.
作为结论,我认为 new
的分配对于大多数问题来说更好。但是 VLA 有利于在函数中进行局部快速内存分配。没有从函数 return VLA 的可移植方法(无需通过汇编进行破解)(您可以从函数 return 具有恒定大小的数组,但是需要在签名中指定)。为此,有 std::array
和 std::vector
,我建议使用它而不是手工制作的内存管理(分配 new
和 delete
或 Cs malloc
和 free
),它在引发异常时不会被释放。如果您需要使用此类函数,Memory-management 应始终嵌套在 class 的构造函数和析构函数中。当对象超出范围时,总是会调用析构函数,因此没有内存泄漏。
VLA 和 new
/delete
不能做的一件事是快速调整大小。甚至 std::vector
也不使用它。这是通过 C-function realloc
完成的,它试图将缓冲区保持在原位。当你需要这个时,你可以轻松地设计一个 std::vector
-like class,它应该在析构函数中调用 free
。要销毁调用 element.~T()
的元素,其中 T
是 element
.
的类型
但是 std::vector
试图通过分配一个缓冲区来提高调整大小的性能 space。
这两种方法的主要区别在于第一种方法从Free-store(堆)分配内存,第二种方法从堆栈分配。事实上,第二个不好用,因为与堆相比,堆栈内存在 space 中非常有限。同样,第一个语句显然 returns 指向分配内存中第一个元素的指针,而第二个 returns 数组本身。
我见过两种在 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 不需要是 free
d/delete
d,当函数退出时它会自动释放。
这适用于 GNU-Compilers:VLA 会在销毁时调用析构函数,但是使用 alloca
/__builtin_alloca
分配的内存将在函数结束时作为内存(分配malloc
) 释放 free
.
作为结论,我认为 new
的分配对于大多数问题来说更好。但是 VLA 有利于在函数中进行局部快速内存分配。没有从函数 return VLA 的可移植方法(无需通过汇编进行破解)(您可以从函数 return 具有恒定大小的数组,但是需要在签名中指定)。为此,有 std::array
和 std::vector
,我建议使用它而不是手工制作的内存管理(分配 new
和 delete
或 Cs malloc
和 free
),它在引发异常时不会被释放。如果您需要使用此类函数,Memory-management 应始终嵌套在 class 的构造函数和析构函数中。当对象超出范围时,总是会调用析构函数,因此没有内存泄漏。
VLA 和 new
/delete
不能做的一件事是快速调整大小。甚至 std::vector
也不使用它。这是通过 C-function realloc
完成的,它试图将缓冲区保持在原位。当你需要这个时,你可以轻松地设计一个 std::vector
-like class,它应该在析构函数中调用 free
。要销毁调用 element.~T()
的元素,其中 T
是 element
.
但是 std::vector
试图通过分配一个缓冲区来提高调整大小的性能 space。
这两种方法的主要区别在于第一种方法从Free-store(堆)分配内存,第二种方法从堆栈分配。事实上,第二个不好用,因为与堆相比,堆栈内存在 space 中非常有限。同样,第一个语句显然 returns 指向分配内存中第一个元素的指针,而第二个 returns 数组本身。