'new' 和 'delete' 在 C++ 中被弃用了吗?
Are 'new' and 'delete' getting deprecated in C++?
我偶然发现了一个涉及不同大小的数组声明的测验。我想到的第一件事是我需要使用 new
命令进行动态分配,如下所示:
while(T--) {
int N;
cin >> N;
int *array = new int[N];
// Do something with 'array'
delete[] array;
}
但是,我看到其中一种解决方案允许以下情况:
while(T--) {
int N;
cin >> N;
int array[N];
// Do something with 'array'
}
经过一番研究后,我了解到 g++ 允许这样做,但这让我一直在思考,在哪些情况下有必要使用动态分配?还是编译器将其翻译为动态分配?
包括删除功能。但是请注意,这里的问题与内存泄漏无关。
您的第二个示例使用 variable length arrays (VLAs), which are actually a C99 (not C++!) feature, but nonetheless supported by g++。
另见 。
请注意,可变长度数组与 new
/delete
不同,并且不要以任何方式 "deprecate" 它们。
另请注意,VLA 不是 ISO C++。
嗯,首先,new
/delete
不会被弃用。
不过,在您的具体情况下,它们并不是唯一的解决方案。您选择什么取决于您的 "do something with array" 评论下隐藏的内容。
你的第二个例子使用了一个非标准的 VLA 扩展,它试图让数组适合堆栈。这有一定的局限性——即大小有限,并且在数组超出范围后无法使用此内存。你不能将它移出,它会在堆栈展开后 "disappear"。
因此,如果您的唯一目标是进行本地计算,然后丢弃数据,它实际上可能工作正常。然而,更稳健的方法是动态分配内存,最好使用 std::vector
。这样你就可以根据运行时值(这是我们一直在做的)为你需要的元素创建 space,但它也会很好地自我清理,而且你如果您想保留内存供以后使用,可以将其移出此范围。
回到开头,vector
可能会用到 new
更深的几层,但你不必担心,因为它呈现的界面要好得多。从这个意义上讲,可以认为不鼓励使用 new
和 delete
。
您显示的两个片段都不是惯用的现代 C++ 代码。
new
和 delete
(以及 new[]
和 delete[]
)在 C++ 中没有被弃用,而且永远不会被弃用。它们仍然是 实例化动态分配对象的方式。但是,由于您必须始终匹配 new
和 delete
(以及 new[]
和 delete[]
),因此最好将它们保存在(库)类 为您确保这一点。参见 Why should C++ programmers minimize use of 'new'?。
您的第一个代码段使用 "naked" new[]
,然后从不 delete[]
创建数组。那是个问题。 std::vector
可以满足您的一切需求。它将在幕后使用某种形式的 new
(我不会深入探讨实现细节),但对于您必须关心的所有内容,它是一个动态数组,但更好更安全。
您的第二个片段使用了 "variable length arrays" (VLAs),这是一个 C 特性,一些 编译器也允许在 C++ 中作为扩展。与 new
不同,VLA 本质上是在堆栈上分配的(非常有限的资源)。但更重要的是,它们不是标准的 C++ 功能,应该避免使用,因为它们不可移植。它们当然不会取代动态(即堆)分配。
第一个例子最后需要一个delete[]
,否则会发生内存泄漏。
第二个例子使用了C++不支持的可变数组长度;它只允许数组长度的常量表达式。
在这种情况下,使用 std::vector<>
作为解决方案很有用;它将您可以对数组执行的所有操作包装到模板中 class.
现代 C++ 提供了更简单的方法来处理动态分配。一旦引用的数据结构超出范围,智能指针可以在异常(如果允许的情况下可能发生在任何地方)和早期 returns 之后进行清理,因此使用它们可能是有意义的:
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();
从 C++ 14 开始,您还可以编写
auto buffer_new = std::make_unique<int[]>(size);
这看起来更好,并且可以在分配失败时防止内存泄漏。从 C++ 20 开始,您应该可以做
auto a = std::make_shared<int[]>(size);
这对我来说在使用 gcc 7.4.0 编写时仍然无法编译。在这两个示例中,我们也使用 auto
代替左侧的类型声明。在所有情况下,照常使用数组:
buffer_old[0] = buffer_new[0] = 17;
内存泄漏 new
和双倍 delete
崩溃是 C++ 多年来一直受到抨击的问题,成为切换到其他语言的争论 "central point"。也许最好避免。
语法看起来像 C++,但惯用语类似于普通的老式 Algol60。像这样的代码块很常见:
read n;
begin
integer array x[1:n];
...
end;
例子可以写成:
while(T--) {
int N;
cin >> N;
{
int array[N];
// Do something with 'array'
}
}
我有时会想念当前语言中的这个 ;)
new 和 delete 没有被弃用。
new操作符创建的对象可以通过引用传递。
可以使用 delete 删除对象。
new 和 delete 是语言的基础方面。
可以使用 new 和 delete 来管理对象的持久性。
这些绝对不会被弃用。
语句 - int array[N] 是一种定义数组的方法。该数组可以在封闭代码块的范围内使用。它不能像对象传递给另一个函数那样传递。
我偶然发现了一个涉及不同大小的数组声明的测验。我想到的第一件事是我需要使用 new
命令进行动态分配,如下所示:
while(T--) {
int N;
cin >> N;
int *array = new int[N];
// Do something with 'array'
delete[] array;
}
但是,我看到其中一种解决方案允许以下情况:
while(T--) {
int N;
cin >> N;
int array[N];
// Do something with 'array'
}
经过一番研究后,我了解到 g++ 允许这样做,但这让我一直在思考,在哪些情况下有必要使用动态分配?还是编译器将其翻译为动态分配?
包括删除功能。但是请注意,这里的问题与内存泄漏无关。
您的第二个示例使用 variable length arrays (VLAs), which are actually a C99 (not C++!) feature, but nonetheless supported by g++。
另见
请注意,可变长度数组与 new
/delete
不同,并且不要以任何方式 "deprecate" 它们。
另请注意,VLA 不是 ISO C++。
嗯,首先,new
/delete
不会被弃用。
不过,在您的具体情况下,它们并不是唯一的解决方案。您选择什么取决于您的 "do something with array" 评论下隐藏的内容。
你的第二个例子使用了一个非标准的 VLA 扩展,它试图让数组适合堆栈。这有一定的局限性——即大小有限,并且在数组超出范围后无法使用此内存。你不能将它移出,它会在堆栈展开后 "disappear"。
因此,如果您的唯一目标是进行本地计算,然后丢弃数据,它实际上可能工作正常。然而,更稳健的方法是动态分配内存,最好使用 std::vector
。这样你就可以根据运行时值(这是我们一直在做的)为你需要的元素创建 space,但它也会很好地自我清理,而且你如果您想保留内存供以后使用,可以将其移出此范围。
回到开头,vector
可能会用到 new
更深的几层,但你不必担心,因为它呈现的界面要好得多。从这个意义上讲,可以认为不鼓励使用 new
和 delete
。
您显示的两个片段都不是惯用的现代 C++ 代码。
new
和 delete
(以及 new[]
和 delete[]
)在 C++ 中没有被弃用,而且永远不会被弃用。它们仍然是 实例化动态分配对象的方式。但是,由于您必须始终匹配 new
和 delete
(以及 new[]
和 delete[]
),因此最好将它们保存在(库)类 为您确保这一点。参见 Why should C++ programmers minimize use of 'new'?。
您的第一个代码段使用 "naked" new[]
,然后从不 delete[]
创建数组。那是个问题。 std::vector
可以满足您的一切需求。它将在幕后使用某种形式的 new
(我不会深入探讨实现细节),但对于您必须关心的所有内容,它是一个动态数组,但更好更安全。
您的第二个片段使用了 "variable length arrays" (VLAs),这是一个 C 特性,一些 编译器也允许在 C++ 中作为扩展。与 new
不同,VLA 本质上是在堆栈上分配的(非常有限的资源)。但更重要的是,它们不是标准的 C++ 功能,应该避免使用,因为它们不可移植。它们当然不会取代动态(即堆)分配。
第一个例子最后需要一个delete[]
,否则会发生内存泄漏。
第二个例子使用了C++不支持的可变数组长度;它只允许数组长度的常量表达式。
在这种情况下,使用 std::vector<>
作为解决方案很有用;它将您可以对数组执行的所有操作包装到模板中 class.
现代 C++ 提供了更简单的方法来处理动态分配。一旦引用的数据结构超出范围,智能指针可以在异常(如果允许的情况下可能发生在任何地方)和早期 returns 之后进行清理,因此使用它们可能是有意义的:
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();
从 C++ 14 开始,您还可以编写
auto buffer_new = std::make_unique<int[]>(size);
这看起来更好,并且可以在分配失败时防止内存泄漏。从 C++ 20 开始,您应该可以做
auto a = std::make_shared<int[]>(size);
这对我来说在使用 gcc 7.4.0 编写时仍然无法编译。在这两个示例中,我们也使用 auto
代替左侧的类型声明。在所有情况下,照常使用数组:
buffer_old[0] = buffer_new[0] = 17;
内存泄漏 new
和双倍 delete
崩溃是 C++ 多年来一直受到抨击的问题,成为切换到其他语言的争论 "central point"。也许最好避免。
语法看起来像 C++,但惯用语类似于普通的老式 Algol60。像这样的代码块很常见:
read n;
begin
integer array x[1:n];
...
end;
例子可以写成:
while(T--) {
int N;
cin >> N;
{
int array[N];
// Do something with 'array'
}
}
我有时会想念当前语言中的这个 ;)
new 和 delete 没有被弃用。
new操作符创建的对象可以通过引用传递。 可以使用 delete 删除对象。
new 和 delete 是语言的基础方面。 可以使用 new 和 delete 来管理对象的持久性。 这些绝对不会被弃用。
语句 - int array[N] 是一种定义数组的方法。该数组可以在封闭代码块的范围内使用。它不能像对象传递给另一个函数那样传递。