【问题标题】:Vector assignment crashing向量分配崩溃
【发布时间】:2021-12-31 07:06:27
【问题描述】:
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
    vector< vector<int> > newMatrix;
    int i,j;

    for (i = 0; i < m[i].size(); i++)
    {
        for(j = 0; j < m[j].size(); j++)
        {
            newMatrix[i][j] = m[i][j];
        }
    }
    return (newMatrix);
}

我正在制作一个可以进行大量矩阵操作的程序,但这个部分崩溃了,我不知道为什么。我已将其范围缩小到这一行:

newMatrix[i][j] = m[i][j];

它就在这里崩溃,我不知道为什么。

【问题讨论】:

    标签: c++ matrix vector error-handling indexoutofboundsexception


    【解决方案1】:

    除了@Saurav 发布的内容之外,newMatrix 是空的,因此您无法将值分配给newMatrix[i][j]。您可以通过使用给定大小初始化向量来解决此问题:

    vector< vector<int> > resizeVector(vector< vector<int> > m)
    {
        vector< vector<int> > newMatrix(m.size());
        int i,j;
    
        for (i = 0; i < m.size(); i++)
        {
            newMatrix[i].resize(m[i].size());
            for(j = 0; j < m[i].size(); j++)
            {
                newMatrix[i][j] = m[i][j];
            }
        }
        return (newMatrix);
    }
    

    在 for 循环之前,我们初始化 newMatrix 以使 m.size() 内部有许多空向量(由于它们的默认构造函数,向量是空的)。在外部 for 循环的每次迭代中,我们使用 resize 成员函数确保 newMatrix 中的每个向量具有正确的大小。

    请注意,如果你想要一个向量的副本,你可以简单地写:

    vector< vector<int> > newMatrix(m);
    

    【讨论】:

      【解决方案2】:

      你的支票错了。相反,它应该是

      for (i = 0; i < m.size(); i++)        // m.size() gives the number of rows 
      {
          for(j = 0; j < m[i].size(); j++)  // m[i].size() gives the number of columns in the row
      

      【讨论】:

        【解决方案3】:

        您将分配给新的newMatrix,而没有先设置其大小。它将默认为空,并且 任何 尝试分配给它都会导致未定义的行为。

        由于您没有传入新的尺寸,因此很难确切知道您想要完成什么。这就是为什么我没有更明确的建议来解决它。

        【讨论】:

          【解决方案4】:

          如果要分配向量的向量,则需要在对矩阵进行索引之前为矩阵分配内存。所以你将不得不使用像

          这样的东西
          newMatrix.resize(size);
          for (int i = 0; i < size; ++i) {
              newMatrix[i].resize(size);
          }
          

          或者您可以使用 .push_back() 向量方法向向量添加值,而无需事先分配内存。

          【讨论】:

            【解决方案5】:

            vectors operator[] 返回对指定元素的引用而不进行边界检查。

            这意味着它不会神奇地调整向量的大小,也不会执行任何其他操作来确保元素存在。如果元素不存在,则结果是未定义的行为——这意味着任何事情都可能发生。实际上,它经常导致程序访问无效的内存位置,从而导致崩溃。

            即使对于简单的vector&lt;int&gt;,上述情况也是如此。通过使用 vector&lt;vector&lt;int&gt; &gt;vector&lt;vector&lt;int&gt; &gt; 的每个元素都是 vector&lt;int&gt;),您的问题变得更加复杂。

            您的函数实际上可能调用未定义行为的次数有点惊人。您碰巧在声明 newMatrix[i][j] = m[i][j] 时遇到了崩溃,但未定义行为的可能性实际上发生在此之前。

            在外部循环中,如果m.size()(您的代码不会检查)的值为零,则m[i] 将不存在。如果m.size() 为零,这将导致m[i](如m.operator[](i))的评估具有未定义的行为。

            本质上,您需要在评估m[i] 之前确保任何索引i 有效,然后还要确保jm[i] 的有效索引,然后再评估m[i][j]。然后对newMatrix 执行相同的操作。您的代码根本不执行此操作。更正确的函数渲染(假设意图是创建m 的副本)是

            vector< vector<int> > resizeVector(vector< vector<int> > m)
            {
                vector< vector<int> > newMatrix;
                int i,j;
            
                newMatrix.resize(m.size());    //  necessary to ensure we can access newMatrix[i] in the loop below
            
                for (i = 0; i < m.size(); i++)     //   ensure i is a valid index of m
                {
                    // newMatrix[i].size() is still zero, so we need to resize for use in the inner loop
            
                    newMatrix[i].resize(m[i].size()); 
            
                    for(j = 0; j < m[i].size(); j++)   // ensure j is a valid index of m[i]
                    {
                        newMatrix[i][j] = m[i][j];
                    }
                }
                return (newMatrix);
            }
            

            现在,问题是,您的代码实际上是在重新创建 vector 已经提供的功能。所以,我们可以很简单地用

            替换函数的主体
            vector< vector<int> > resizeVector(vector< vector<int> > m)
            {
                  vector< vector<int> > newMatrix(m);  
                  return newMatrix;
            }
            

            甚至与

            vector< vector<int> > resizeVector(vector< vector<int> > m)
            {
                  return m;
            }
            

            这意味着你的函数(正如我修改过的)命名错误——它不会调整任何东西的大小。事实上,这是相当没有意义的,因为如果调用者这样做

            x = resizeVector(y);
            

            完全不用你的函数也能达到同样的效果,就像

            x = y;
            

            这也更有效(没有函数调用,没有创建副本以通过值传递等)。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-03-31
              • 1970-01-01
              • 2010-11-14
              • 1970-01-01
              • 2015-04-18
              相关资源
              最近更新 更多