【问题标题】:Array size at run time without dynamic allocation is allowed?允许在没有动态分配的情况下运行时的数组大小?
【发布时间】:2010-10-18 17:52:12
【问题描述】:

我已经使用C++几年了,今天看到了一些代码,但这怎么可能完全合法呢?

int main(int argc, char **argv)
{
    size_t size;
    cin >> size;
    int array[size];
    for(size_t i = 0; i < size; i++)
    {
        array[i] = i;
        cout << i << endl;
    }

    return 0;
}

在 GCC 下编译。

如果没有newmalloc,如何在运行时确定大小?

只是为了仔细检查,我已经用谷歌搜索了一些和所有与我相似的代码都声称会给出存储大小错误。

甚至 Deitel 的 C++ 如何编程 p。常见编程错误 4.5 下的 261 个状态:

只有常量可以用来声明自动和静态数组的大小。

启发我。

【问题讨论】:

标签: c++ c array-initialization


【解决方案1】:

这在 C99 中有效。

C99 标准支持堆栈上的可变大小数组。可能你的编译器也选择了支持这个结构。

请注意,这与 mallocnew 不同。 gcc 在堆栈上分配数组,就像它对 int array[100] 所做的那样,只需调整堆栈指针即可。没有进行堆分配。很像_alloca

【讨论】:

  • 我在几个月前编写的代码库中的一个文件中遇到了同样的场景。我和团队的其他人一样,对它编译的原因感到困惑。在我们的情况下,数组的大小也是在声明数组之前计算的(这也不应该被允许吗?)无论如何,一个挑战出来了。任何能回答为什么这是合法的人都会得到一个流行馅饼。如果你在西雅图,请告诉我。我有一个流行馅饼给你。
  • 您能否提供一些关于在这种情况下堆栈内部如何工作的信息/链接?这是否会在运行时引入一些开销?
  • @balki 开销很小,因为它基本上是递增/递减堆栈指针。如果将原始堆栈指针保存在函数开头,则堆栈行为基本上与正常情况相同。
  • 这在 c++ 中是否允许? Visual Studio 不允许这样做?
【解决方案2】:

仅在 C99 中为 valid。下次您可以尝试在reliable compiler 中检查您的代码。

【讨论】:

    【解决方案3】:

    它是有效的 C99,它不是有效的 C++。这是两种语言之间的众多差异之一。

    【讨论】:

    • 我猜C++0x会支持它
    • 不符合标准草案第 8.3.4 节。
    • 它永远不会包含在 c++1x 中:D 但让我们希望 dynarray 进入。我会喜欢它。所以你可以做 dynarray a(some_size);并让它有效地分配,可能使用像 _alloca 之类的编译器 hax 等等。
    • 对于未来的任何人:它将包含在 C++14 中(具有较小的功能集,例如 typedef、sizeof() 等)。
    • @RedXIII:猜错了。 VLA 和 dynarray 都不是 C++14 的一部分。
    【解决方案4】:

    这称为 VLA(可变长度数组)。它在 c99 中是标准的,但 gcc 允许它在 c++ 代码中作为扩展。如果您希望它拒绝代码,请尝试使用-std=standard-ansi-pedantic 选项。

    【讨论】:

    • -std-ansi 选项与此扩展完全无关。
    【解决方案5】:

    如果您使用的是 Dev-Cpp 编译器,您可以动态地为数组指定大小我已经尝试过了 并且没有错误,但在 Visual c++ 和 Visual Studio 编译器上这是不可能的。 我认为原因是 dev-c++ 为未初始化的 int 分配了一个正数 当我们给它一个数字时,它会被给定的数字所取代。 但也许其他编译器会将 null 赋予未初始化的变量。

    【讨论】:

    • 大多数编译器不会为未初始化的局部变量分配任何东西,它们通常看起来会保存它们占用的内存中的任何东西,直到它们被程序分配。您引用的 Dev-C++ 似乎是 MinGW 之上的 IDE,其中包括一个 GCC 端口作为编译器。如其他答案所述,VLA 不是标准 C++,但一些编译器(包括 g++)无论如何都支持它们。
    • Dev-C++ 不是编译器。 Visual Studio 也不是。 Dev-C++ 使用 GCC/G++ 作为其编译器,而 Visual Studio 使用 cl(微软的编译器后端)。 Dev-C++ 和 Visual Studio 本身就是集成开发环境 (IDE)。这是一个重要的区别。 Dev-C++ 不会“分配”任何东西。编译器会这样做。
    【解决方案6】:

    C++14 标准支持可变长度数组 (VLA),该标准最近已被接受,正在等待发布。

    【讨论】:

    • VLA 仍然不是标准的一部分。有一个dynarray TS,但目前还没有被批准。
    【解决方案7】:

    此代码在 GNU GCC 编译器中运行。

    #include<bits/stdc++.h>
    
    int main(int argc, char **argv)
    
    {
        size_t size;
    
       std:: cin >> size;
    
        int array[size];
    
        for(size_t i = 0; i < size; i++)
    
    {
    
    array[i] = i;
    
            std:: cout << i;
    
     }
    
        return 0;
    }
    

    【讨论】:

      【解决方案8】:

      我最近遇到了一个需要堆栈分配数组的场景。 (它是 v8 的包装器,每次方法调用都需要一个 args 数组)。

      std::vector 会做堆内存分配,其性能无法接受。

      这是我的解决方案,使用模板分配案例数组:

      template<size_t Argc>
      static void call(...) {
          v8::Local<v8::Value> v8Args[Argc];
      
          // use v8Args
          ...
      }
      
      template<typename It>
      static void callV8Function(size_t argc, It argvBegin, It argvEnd,) {
          // C++ don't have dynamic stack allocation (like C99 does)
          // try to avoid heap-allocation...
          if (argc <= 4) {
              return callV8FunctionOnStack<4>(...);
          } else if (argc <= 8) {
              return callV8FunctionOnStack<8>(...);
          } else if (argc <= 16) {
              return callV8FunctionOnStack<16>(...);
          } else if (argc <= 32) {
              return callV8FunctionOnStack< 32>(...);
          } else {
              std::vector<v8::Local<v8::Value>> v8Args(argc);
              // fallback to vector
         }
      }
      

      (当然,我可以只使用 32 大小的数组,但这不是那么优雅。)

      【讨论】:

        猜你喜欢
        • 2016-04-06
        • 1970-01-01
        • 2018-08-21
        • 2013-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-12
        相关资源
        最近更新 更多