使用变量定义数组大小和使用新运算符 c++ 有什么区别?

What's the difference between using a variable to define array size and using the new operator c++?

我正在根据“http://www.cplusplus.com/doc/tutorial/dynamic/”的官方教程,利用之前在 Java 的经验学习 C++ 的基础知识。本教程介绍了运算符 "new" 作为一种在运行时定义数组大小的方法;然而,这感觉像是一个无用的添加,因为我可以通过

轻松地用变量定义数组的大小
int numbers [size];

对比

int * numbers = new int [size];

通过我自己的测试,我已经意识到使用 new 运算符可以超过预分配的内存大小(当我用 size = 5 初始化它时,我可以写入 numbers[7]),而第一个代码行没有。关于这个运算符,我有三个基本问题:

  1. 上面两行代码有什么区别?
  2. 在我没有分配开始的数组中写入内存中的指针地址是否危险?
  3. 如果这样做很危险,除了手动设置(或使用库)链表之外,我可以使用什么替代方法(如果有的话)来设置列表?

What's the difference between the two lines of code above?

假设size是一个常量表达式,区别在于第一个例子分配在栈上,而第二个例子分配在堆上,你需要记住delete []它。

Is it dangerous to write to a pointer address in memory in the array I didn't allocate to start with?

写在边界外是未定义的行为,但如果你在边界内就没问题:

constexpr int size = 5;
int arr[size];
arr[0] = 2;

If it is dangerous to do so, what alternative could I use

使用 std::vector:

std::vector<int> arr;

What's the difference between the two lines of code above?

区别在于第一个在C++中是不允许的。 Some compilers will allow it and may give a warning when special flags are supplied, whereas other compilers看到就想吐。

第二个是要走的路,无论您使用什么编译器,几乎都做同样的事情。

Is it dangerous to write to a pointer address in memory in the array I didn't allocate to start with?

是的。 behavior is undefined。如果你在运行时没有得到任何异常,不要认为这是一件好事,因为迟早会出人意料地出问题。

If it is dangerous to do so, what alternative could I use (if there is one) to setting up lists other than manually setting up (or using a library for) a linked list?

您是否正在寻求一种替代方法来访问不属于您的内存?答案是不要这样做!

您可以使用 C++ 的容器之一来替代创建内容列表。对于内置链表数据结构,使用 std::list or std::forward_list. For random access containers, std::vector is a great start, but if you know the size ahead of time (i.e. before runtime), then std::array 是可行的方法。

int numbers [size];

in contrast to

int * numbers = new int [size];

首先,在标准 C++ 中,要求 size 的值在编译时已知并固定。第二个允许在 运行 时间确定 size 的值(例如,基于用户输入)。

一些编译器允许第一种形式作为变量与 size 一起使用,但这不是标准的 C++。这种可变长度数组是 C(从 1999 年开始)的一个特性,一些 C++ 编译器支持将其作为 non-standard 扩展。其他 C++ 编译器将诊断错误(根据 C++ 标准的要求)。

如何分配第一个取决于上下文。例如;

  • 如果在函数之外(例如在文件范围内),它将被静态分配,并且只要程序 运行s 就会存在。
  • 如果在一个块内(例如在一个函数中)arr 将具有自动存储持续时间并且将在封闭块的末尾停止存在(例如当函数 returns 时)。
  • 如果 structclass 类型的成员,则每当创建 structclass 的实例时都会创建数组。

上面的前两个有些不正确,有时说是在“堆栈”上创建的。但是,C++ 标准并不要求 - “堆栈”是与操作系统和 运行 时间环境相关的实现细节。

第二种据说是动态分配内存(使用运算符new)。内存将一直存在,直到它被显式释放(例如使用相应的运算符delete)。

Is it dangerous to write to a pointer address in memory in the array I didn't allocate to start with?

是的。 C++ 标准未定义此行为。实际上,它似乎可以正常工作。它还可能产生不良影响,例如程序使用的数据中毒或重新格式化硬盘。在恶劣的情况下,它在您的测试中似乎可以正常工作,但只有在付费客户 运行 时才会产生不良影响之一。这种情况往往会导致脾气暴躁的客户。

无论是使用指针还是数组,行为都同样未定义。为具有五个元素的数组的第十个元素赋值会产生未定义的行为,无论数组是如何创建的(例如,在您的两个选项中的任何一个)。

If it is dangerous to do so, what alternative could I use (if there is one) to setting up lists other than manually setting up (or using a library for) a linked list?

在 C++ 中,有标准的容器。查找 vector(在标准 header <vector> 中)作为示例。显然,可能会错误地使用标准容器(并产生不良影响),但使用标准容器比使用数组或指针更容易避免问题。

标准容器也会自动处理内存分配和释放——作为程序员,您无需直接管理动态内存(例如忘记释放不再需要的内存)。