【问题标题】:How to initialize a 2D array with all values same?如何初始化所有值相同的二维数组?
【发布时间】:2020-09-29 20:04:06
【问题描述】:

我想用 -1 作为所有值初始化一个二维数组。我为此使用了memset()

#include <bits/stdc++.h>
using namespace std;

int dp[100][100];
memset(dp, -1, sizeof(dp));

int dynamicProgramming(some parameters)
{
    //I want to use dp[][] array here
}

int main() {
    cout<<dp[99][99];
    return 0;
}

但是我得到一个错误

prog.cpp:5:7: error: expected constructor, destructor, or type conversion before ‘(’ token
 memset(dp, -1, sizeof(dp));

你能告诉我正确的做法吗?

【问题讨论】:

  • 你不能在函数之外有像memset(...)这样的可执行语句!将该行放入 main。另请参阅:Why should I not #include <bits/stdc++.h>?
  • 请参阅您的 C++ 教科书。所有 C++ 代码都必须出现在某个函数或类方法中,而不是像这样的全局初始化部分。也许你可以将 memset 调用移到 main() 中。尽管如此,这种方法还有其他几个基本问​​题是错误的。
  • 这种方式不能初始化全局变量。 C++ 不能以这种方式工作。您将需要找到其他方法来解决您的问题。
  • 注意 memset 是按字节初始化的!由于没有最近的机器不再使用 2 的补码,因此您很可能是 幸运 并以这种方式获得所需的结果,因为每个 int 的所有四个字节看起来都相似。但是,请尝试使用 +1,您会得到完全不同的结果。 (提示:在典型的现代 64 位和较旧的 32 位硬件上,它等于 1 + 256 + 256² + 256³。)
  • 我不知道“动态编程”是什么意思,而且,无论如何,C++ 仍然不能这样工作。无论您尝试做什么,您都无法从根本上改变 C++ 的工作方式。这里唯一可以做的就是使用std::array 和一个初始化函数。不过,这将是非常低效的。有关如何使用 std::array 的更多信息和说明,请参阅 C++ 教科书。

标签: c++ memset


【解决方案1】:

没有办法(至少我不知道)初始化具有特定值而不是0 的数组的所有元素。

您可以在文件范围内初始化另一个变量的过程中调用memset

int dp[100][100];
auto x = memset(dp, -1, sizeof(dp));

int main() {
    cout<<dp[99][99];
    return 0;
}

但注意:全局变量初始化的顺序是不保证的;您唯一可以依赖的是memset 将在输入函数main 之前执行。但是您也可以将其作为main 中的第一行。

进一步注意,当您想要初始化int 类型的数组元素时,您需要好运,因为单个 int 包含多个字节; memset 在字节级别填充元素,而不是在元素类型级别。例如,memset(dp, -2, sizeof(dp))不会 导致一个填充有 -2 的数组;甚至-1 也要求架构是二进制的补充才能工作。

【讨论】:

  • 技术上不完全正确,因为 x 的初始化可以推迟 - 但是在 C++17 之前,这可能会严重失败,因为推迟到第一次 ODR 使用 x 之前是合法的(并且 dp 可能有之前访问过)。我认为向初学者展示这样的代码并不是一个好主意——尤其是如果你不展示一个人通常会怎么做……
【解决方案2】:

正如其他人所说,您不能在全局范围内调用memset。最正确和最清楚的 vay 可能是这样的

#include <iostream>
using namespace std;

const int D1 = 100;
const int D2 = 100;
int dp[D1][D2];

void initializeDp()
{
    for (int i = 0; i < D1; i++) {
        for (int j = 0; j < D2; j++) {
            dp[i][j] = -1;
        }
    }
}

int main() {
    initializeDp();
    cout << dp[D1-1][D2-1];
    return 0;
}

显然,如果您将全局变量视为一种好习惯。 我个人会使用 2d std::array,所以它会包含它本身的大小

【讨论】:

    【解决方案3】:

    你不能在全局范围内使用 memset。 它必须写在主范围内。

    #include <bits/stdc++.h>
    using namespace std;
    
    int dp[100][100];
    
    int main() {
        memset(dp, -1, sizeof(dp));
        cout<<dp[99][99];
        return 0;
    }
    

    【讨论】:

    • memset 的正确位置——不过,问题是“如何初始化二维数组?”,而 memset 不是要走的路。你也应该解决这个问题。
    【解决方案4】:
    for (auto& v : dp) {
        std::fill(std::begin(v), std::end(v), -1);
    }
    

    内部函数,而不是全局范围。

    【讨论】:

      【解决方案5】:

      在实践中,在这种情况下,可以编写一个帮助模板化的函数,它本身基于简单的 for-range 循环。

      一个优点是它适用于其他类型的二维数组。

      #include    <iostream>
      
      template <typename T2d, typename T>
      void init2d (T2d &arr, T val) {
          for (auto& row: arr) {
              for (auto& i: row) {
                  i = val;
              }
          }       
      }
      
      int main() {
          const int  n = 5, m = 6;
          int a[n][m];
      
          init2d (a, -1);
          std::cout << a[n-1][m-1] << "\n";
      }
      

      如果你想在main之前初始化,最简单的方法就是依赖STL,例如在 std::vectorstd::array 上,像这样,对于 5x6 矩阵:

      std::vector<std::vector<int>> b(5, std::vector<int> (6, -1));
      

      【讨论】:

      • 我正准备用这里提到的矢量解决方案写一个答案,虽然你需要在&gt;&gt;中添加一个空格,即std::vector&lt;std::vector&lt;int&gt; &gt; b(5, std::vector&lt;int&gt; (6, -1));(编辑队列已满,所以我写了这个评论以便人们可以看到为什么该示例无法编译)。
      • @Nikolaj 实际上,这个空间在标准的最后一个版本中不再有用(如果我记得清楚的话,从 C++14 开始)。
      【解决方案6】:

      您似乎正在寻找一种在main 之前初始化全局数组的方法,如Call a function before main 中所述?通常我会建议避免编译器特定的扩展,但你的代码已经是编译器特定的,对你来说似乎没问题。这是一个 gcc 扩展。它可能会导致奇怪的错误。其他全局对象可能未初始化。此代码的某些部分可能会导致未定义的行为。如果你想在你的脚上开枪,那就去做吧。

      #include <bits/stdc++.h>
      using namespace std;
      
      void beforeMain (void) __attribute__((constructor));
      
      int dp[100][100];
      void beforeMain (void) {
          memset(dp, -1, sizeof(dp));
      }
      
      int main() {
          std::cout << dp[0][0] << std::endl;
      }
      

      【讨论】:

        猜你喜欢
        • 2016-12-09
        • 1970-01-01
        • 1970-01-01
        • 2011-12-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-29
        相关资源
        最近更新 更多