lea*_*ude 68 c++ arrays dynamic-memory-allocation static-memory-allocation
我偶然发现了一个涉及不同大小数组声明的测验。我想到的第一件事是我需要对new
命令使用动态分配,如下所示:
while(T--) {
int N;
cin >> N;
int *array = new int[N];
// Do something with 'array'
delete[] array;
}
Run Code Online (Sandbox Code Playgroud)
但是,我看到其中一种解决方案允许以下情况:
while(T--) {
int N;
cin >> N;
int array[N];
// Do something with 'array'
}
Run Code Online (Sandbox Code Playgroud)
经过一番研究,我读到 g++ 允许这样做,但它让我一直在思考,在哪些情况下有必要使用动态分配?还是编译器将其翻译为动态分配?
包括删除功能。但是请注意,这里的问题与内存泄漏无关。
Max*_*hof 117
您展示的两个片段都不是惯用的现代 C++ 代码。
new
and delete
(and new[]
and delete[]
) 在 C++ 中不会被弃用,也永远不会被弃用。它们仍然是实例化动态分配对象的方式。但是,由于您必须始终将 anew
与 a delete
(以及 anew[]
与 a delete[]
)匹配,因此最好将它们保存在(库)类中,以确保这一点。请参阅为什么 C++ 程序员应尽量减少“new”的使用?.
您的第一个代码段使用“裸” new[]
,然后从不delete[]
使用创建的数组。这是个问题。std::vector
在这里你需要的一切都很好。它将使用某种形式new
的幕后(我不会深入研究实现细节),但对于您必须关心的所有内容,它是一个动态数组,但更好更安全。
您的第二个代码段使用“可变长度数组”(VLA),这是一些编译器还允许在 C++ 中作为扩展的 C 特性。与 不同new
,VLA 本质上是在堆栈上分配的(非常有限的资源)。但更重要的是,它们不是标准的 C++ 特性,应避免使用,因为它们不可移植。它们当然不会取代动态(即堆)分配。
Bar*_*icz 24
好吧,对于初学者来说,new
/delete
并没有被弃用。
不过,在您的具体情况下,它们不是唯一的解决方案。你选择什么取决于你的“用数组做某事”评论下隐藏的内容。
您的第二个示例使用非标准 VLA 扩展,该扩展尝试将数组放入堆栈中。这有一定的局限性 - 即有限的大小和数组超出范围后无法使用此内存。您无法将其移出,它会在堆栈展开后“消失”。
因此,如果您的唯一目标是进行本地计算,然后将数据扔掉,它实际上可能会正常工作。但是,更健壮的方法是动态分配内存,最好使用std::vector
. 这样,您就可以根据运行时值(这就是我们一直以来的目标)为您需要的元素创建空间,但它也可以很好地清理自己,您可以将其移出如果您想保留内存供以后使用,请使用此范围。
盘旋回到起点,vector
将可能使用new
几层深,但你不应该与关注,因为它提出的界面优越得多。从这个意义上说,使用new
和delete
可以被认为是不鼓励的。
h22*_*h22 13
现代 C++ 提供了更简单的方法来处理动态分配。一旦引用的数据结构超出范围,智能指针可以处理异常之后的清理(如果允许,可以在任何地方发生)和提前返回,因此使用它们可能更有意义:
int size=100;
// This construct requires the matching delete statement.
auto buffer_old = new int[size];
// These versions do not require `delete`:
std::unique_ptr<int[]> buffer_new (new int[size]);
std::shared_ptr<int[]> buffer_new (new int[size]);
std::vector<int> buffer_new (size); int* raw_access = buffer_new.data();
Run Code Online (Sandbox Code Playgroud)
从 C++ 14 你也可以写
auto buffer_new = std::make_unique<int[]>(size);
Run Code Online (Sandbox Code Playgroud)
这看起来更好,并且在分配失败时可以防止内存泄漏。从 C++ 20 开始,您应该能够做到
auto a = std::make_shared<int[]>(size);
Run Code Online (Sandbox Code Playgroud)
这对我来说在编写 gcc 7.4.0 时仍然无法编译。在这两个示例中,我们还使用auto
了左侧的替代类型声明。在所有情况下,像往常一样使用数组:
buffer_old[0] = buffer_new[0] = 17;
Run Code Online (Sandbox Code Playgroud)
new
翻倍造成的内存泄漏和崩溃delete
是 C++ 多年来一直受到抨击的事情,它是切换到其他语言的争论的“中心点”。也许最好避免。