【问题标题】:Why do we declare the size of a single or a multi-dimensional array as a constant value?为什么我们将单维或多维数组的大小声明为常量值?
【发布时间】:2020-10-22 17:44:11
【问题描述】:

自从我开始竞争性编程以来,我一直发现人们总是习惯于根据输入规范的最大值中的恒定最大值来初始化单个或二维数组。

但我一直想知道,当您可以根据输入初始化数组时,为什么人们会这样做。

例如,假设在接收数组(或向量)大小的输入时,问题的输入规格为 0 到 10 的 5 次方。

人们为什么这样做:

表示法:整数n代表输入,a代表数组:

#include<bits/stdc++.h>

using namespace std;

const int MXN = 1e5;
int a[MXN], n;

int main() {
    cin >> n;

    for(int i = 0; i<n; i++)
        cin >> a[i];
}

而不是这个:

#include<bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;

    int a[n];

    for(int i = 0; i<n; i++)
        cin >> a[i];
}

或者这是最好的方法(这是我通常做的):

#include<bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int>a(n);

    for(int i = 0; i<n; i++)
        cin >> a[i];

    //for(auto &i:a) cin >> i;
}

这样做有什么好处吗?谢谢。

【问题讨论】:

  • 第一个sn-p是浪费内存或者越界访问,第二个sn-p不是标准的C++。两者都不应该使用,使用std::vector。 (从技术上讲,它们都不是标准 C++,因为 this header)。
  • 首先是因为您正在查看来自“竞争”网站的代码,人们不了解良好的编程实践,并使用许多坏习惯(包括您提出的那个)。 variable-length arrays 也不是标准 C++ 的一部分。
  • 最后,请不要将竞赛网站用作学习或教学资源,或作为可供学习的优质代码的存储库,因为它们不是(我认为他们完全相反)。上课,阅读some good books,在使用此类网站之前正确学习。
  • 这些技术的唯一“优势”(我用宽松的术语)是它们在竞争性编程网站上被接受。如果您想学习在现实世界中不好的编程技术,请继续使用这些方法,如果您希望获得一份像样的工作,作为一名程序员,从事您引以为豪的工作,那么您就必须放弃学习。跨度>

标签: c++ arrays initialization


【解决方案1】:

这三种方法各有优缺点。选择取决于目标。

第一种方法:静态存储时长数组

  • 数组在程序执行期间持续存在,
  • 内存分配在程序启动时执行(可能由操作系统),而且非常便宜
  • 它不提供值语义。 (不能轻易复制、移动或分配)。

这种方法在小型项目中可能对执行速度有好处,但它不可扩展。

第二种方法:栈上分配数组

  • 数组生命周期从其定义开始,到块作用域出口结束
  • 内存分配是在程序执行期间执行的,并且只包含一条非常便宜的汇编指令。
  • 它不提供值语义。 (不能轻易复制、移动或分配)。
  • 它是标准语言的编译器扩展。

这种方法对于临时缓冲区来说是一个不错的选择,但它又一次不可扩展,已知会导致堆栈溢出。

第三种方法:动态分配数组,std::vector

  • 数组生命周期在需要时开始和结束,
  • 内存分配是在程序执行过程中进行的,成本相对较高
  • 它确实提供了值语义。 (可以轻松复制、移动或分配)。

这应该是默认选项。

【讨论】:

    【解决方案2】:

    标准要求数组长度是一个在编译时可计算的值,以便编译器能够在堆栈上分配足够的空间。

    在您的情况下,您尝试将数组长度设置为编译时未知的值。是的,编译器应该知道它似乎很明显,但这里不是这种情况。编译器无法对非常量变量的内容做出任何假设。

    这是我们应该使用常量来声明数组大小的突出原因之一,以便编译器知道在创建数组时应该在堆栈上分配多少内存。

    对于动态分配,我们可以使用data_type variable = new data_type[len] 格式或vector&lt;&gt;。请注意,C99 支持 VLA(关于您尝试声明数组的方式,如 arr[n])。

    举个例子,假设你告诉编译器

    int vla = 100;
    int a[vla];
    

    如果不进行大量非常复杂的分析以追踪vla 值发生变化的每个最后位置,编译器将无法考虑您在运行时实际需要多少内存。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-10
      • 1970-01-01
      • 1970-01-01
      • 2017-03-29
      • 2020-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多