【问题标题】:Instantiation of array class of size unknown at compile time在编译时实例化大小未知的数组类
【发布时间】:2014-07-20 13:28:05
【问题描述】:

下面是一个小脚本,用于打印数字 1 到 n 的总和,其中 n = 1,...,20。

#include <iostream>
#include <array>

using namespace std;

int test(int n)
{
    array<int,n> myArray;

    for (int iii = 0; iii < n; iii++)
        myArray[iii] = iii+1;

    int nSum;

    for (int iii = 0; iii < n; iii++)
        nSum += myArray[iii];

    return nSum;
}


int main()
{
    for (int n = 1; n <= 20; n++)
        cout << test(n) << endl;

    return 0;
}

当然,这不会编译:

Main.cpp: In function ‘int test(long unsigned int)’:
Main.cpp:9:13: error: ‘n’ is not a constant expression
  array<int,n> myArray;
         ^
Main.cpp:9:13: note: in template argument for type ‘long unsigned int’ 
Main.cpp:9:22: error: invalid type in declaration before ‘;’ token
  array<int,n> myArray;
                  ^
Main.cpp:11:26: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int iii = 0; iii < n; iii++)
                      ^
Main.cpp:12:14: error: invalid types ‘int[int]’ for array subscript
   myArray[iii] = iii+1;
          ^
Main.cpp:16:26: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int iii = 0; iii < n; iii++)
                      ^
Main.cpp:17:22: error: invalid types ‘int[int]’ for array subscript
   nSum += myArray[iii];
                  ^
make: *** [Main.o] Error 1

问题似乎是(除其他外)n 不是一个常量表达式,我知道这是一个问题的原因,但我不知道如何解决它。

我知道如何使用新函数实例化“常规”数组,但我不明白数组类如何实现。

如何使test 函数将n 视为常量?

【问题讨论】:

  • 这就是std::vector 的用途。

标签: c++ arrays class instantiation dynamic-arrays


【解决方案1】:

你基本上有两种选择。

  1. 正如您已经提到的,std::array 需要一个编译时大小。所以在编译时让它知道!这可以通过将其转换为模板参数来完成。

    改变

    int test(int n)
    {
      .
      .
      .
    }
    

    template<int n>
    int test()
    {
      .
      .
      .
    }
    

    问题在于,它必须使用test&lt;n&gt;() 而不是test(n) 来调用,这再次要求在编译时也知道调用者代码中的n,但情况并非如此for-循环。如果您在编译时知道循环的上限(例如在当前代码 sn-p 中),则可以完成,但这有点复杂。如果不知道,即用户输入,则根本无法使用此解决方案。

    所以这不是一个好的选择。

  2. 不要使用std::array,而是在编译时但在运行时期间不需要大小的容器类型。正如您所提到的,堆分配的原始数组 (new int[n]) 是一种选择,但它不是很 C++-ish。 改用std::vector

    为此,只需更改

    array<int,n> myArray;
    

    vector<int> myArray(n);
    

    PS。将来,可能会有std::dynarray (proposed container type)std::vector 目前更符合这个目的。它反映了new int[n] 的用途,其中n 在运行时已知,但在数组的生命周期内保持不变,填补了std::arraystd::vector 之间的空白。然而在几乎所有情况下std::vector 都可以!

【讨论】:

  • 这是一个很好的答案,尽管您可能需要在上面澄清一下,目前没有办法解决我的问题,我不能以任何方式将 n 视为常量。
  • 另外,这是不可能的原因,因为模板是“编译器技巧”吗?从技术上讲,我不是必须在运行时“编译”一个新版本的数组(这是不可能的)才能使我的方法起作用吗?
  • 在阅读了一些来自 Rapperswil 的 ISO C++ 会议(2014 年 6 月)的旅行报告后,dynarray 不太可能很快被添加。关于它的问题太多了,没有明确的答案。
【解决方案2】:

您可以改用vector

#include <vector>

vector<int> myArray (n); // n zero-initialized elements

像使用数组一样使用operator[]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-03
    • 2014-09-11
    • 1970-01-01
    • 2021-07-31
    相关资源
    最近更新 更多