【问题标题】:cannot use push_back to insert an integer to a 1D/2D vector不能使用 push_back 将整数插入 1D/2D 向量
【发布时间】:2017-06-26 18:00:46
【问题描述】:

我正在尝试编写一个函数来从给定矩阵中提取切片,其中输入是 1D,切片可以是 1D 或 2D。 我正在尝试为此目的使用push_back 函数,但由于某些原因push_back 不起作用。 我在OutPut.push_back(DumyValue); 行中收到错误消息

谁能帮助我为什么会收到此错误? 另外,如果您能告诉我如何解决这个问题,我们将不胜感激。 另外,如果第一部分变得清晰,谁能告诉我应该如何使用 push_back 在特定位置插入一个整数,以便我可以使用它来提取 2D 切片?

如果删除OutPut.push_back(DumyValue); 行,代码应该可以工作。

#include<iostream>
#include<vector>
using namespace std;



int MatrixSlice(vector<vector<int>> Input, int Row1, int Row2, int Col1, int Col2) {
 //define the slice size, if it is iD or 2D

 if (abs(Row1-Row2)>1 && abs(Col1-Col2)>1){
      vector<vector<int>> OutPut; 
  }else{
      vector<int> OutPut; 
  }

   int i2;
   int j2;

   for (int i = Row1; i <= Row2; i++) {
        i2=0;
       for (int j = Col1; j <= Col2; j++) {
           int DumyValue=Input[i][j];
           OutPut.push_back(DumyValue);
           i2++;
           //cout << Input[i][j] << endl;
       }
       j2++; 
   }


   return 0;
}

int main() {
  //Define a matrix for test:
   vector<vector<int>> Matrix2(4, vector<int>(5, 1));
   int R = 4;
   int C = 4;
   vector<vector<int>> MatrixInput(R, vector<int>(C, 1));;
   for (int i = 0; i < MatrixInput.size(); i++) {
       for (int j = 0; j < MatrixInput[0].size(); j++) {
           int temp;
            temp = i^2+j^2;
           MatrixInput[i][j] = temp;
       }
   }


   MatrixSlice(MatrixInput, 0, 3, 1, 1);
printf("\n");


   return 0;
}

【问题讨论】:

  • 您能否也发布您遇到的错误?
  • 错误:“OutPut”未在此范围内声明 OutPut.push_back(DumyValue);
  • 完全偏离主题警告,因为i^2+j^2 看起来很像您实际上可能想要i*i + j*j 而不是i XOR 2 + j XOR 2^ 是 XOR 运算符,而不是指数运算符。

标签: c++ vector integer push-back


【解决方案1】:

矩阵切片有几个问题:

  1. 不可能用两种可能的类型定义一个变量,并且在同一范围内都处于活动状态。
  2. int 的返回类型毫无意义。矩阵被切分了,然后呢?不能将其交还给调用者以对其进行任何操作。

这可以通过union 来解决,但是哎呀!对此的簿记将是蓝精灵的噩梦。不要这样做!

接下来是始终使用vectors 中的vector,但我不喜欢这个想法,原因我将在下面讨论。

相反,我在单个 vector 周围放置一个简单的包装对象。这样做有两个原因:

  1. 它保留了使用一维容器支持一维矩阵的能力。如果一列有很多行,则所有行数据都保持连续且便于缓存。
  2. 它往往要快得多。一个vector 的数据在内存中是连续的,并获得缓存友好的回报。 vectorvectors 基本上是一个指向数据数组的指针列表,将可怜的 CPU 发送到指针追逐内存以查找列的奥德赛中。如果列很短,这真的会影响性能。

我们开始吧:

template<class TYPE>
class Matrix
{
private:
    size_t mNrRows; // note size_t. This is unsigned because there is no reason 
                    // for a matrix with a negative size. size_t is also guaranteed 
                    // to fit anything you can throw at it.
    size_t mNrColumns;
    std::vector<TYPE> mVec;
public:
    // make a default-initialized matrix
    Matrix(size_t nrRows, size_t nrColumns) :
            mNrRows(nrRows), mNrColumns(nrColumns), mVec(mNrRows * mNrColumns)
    {

    }
    // make a def-initialized matrix
    Matrix(size_t nrRows, size_t nrColumns, TYPE def) :
            mNrRows(nrRows), mNrColumns(nrColumns), mVec(mNrRows * mNrColumns,
                                                        def)
    {

    }

    // gimme a value and allow it to be changed
    TYPE & operator()(size_t row, size_t column)
    {
        // could check for out of bounds and throw an exception here
        return mVec[row * mNrColumns + column];
    }
    //gimme a value and do not allow it to be changed
    TYPE operator()(size_t row, size_t column) const
    {
        return mVec[row * mNrColumns + column];
    }
    // gimme the number of rows
    size_t getRows() const
    {
        return mNrRows;
    }
    // gimmie the number of columns.
    size_t getColumns() const
    {
        return mNrColumns;
    }

    // printing convenience
    friend std::ostream & operator<<(std::ostream & out, const Matrix & mat)
    {
        int count = 0;
        for (TYPE val: mat.mVec)
        {
            out << val;
            if (++count == mat.mNrColumns)
            {
                out << '\n';
                count = 0;
            }
            else
            {
                out << ' ';
            }
        }
        return out;
    }
};

vector 成员处理所有繁重的工作,因此the Rule of Zero 建议将复制和移动构造函数、赋值运算符和析构函数留给编译器处理。

这对MatrixSlice 有什么影响?好吧,首先它现在收到并返回Matrix 而不是vector&lt;vector&gt;int。内部使用Matrix,关于 1D 或 2D 的混淆完全消失了,从而产生了更简单的功能。

Matrix<int> MatrixSlice(const Matrix<int> & Input,
                        int Row1,
                        int Row2,
                        int Col1,
                        int Col2)
{
    Matrix<int> OutPut(Row2-Row1 + 1,
                       Col2-Col1 + 1); // but what if Row1 > Row2?

    int i2;
    int j2= 0; // definitely need to initialize this sucker.

    for (int i = Row1; i <= Row2; i++) // logical problem here: What if Row2 >= input.getRows()?
    {
        i2 = 0;
        for (int j = Col1; j <= Col2; j++) // similar problem here
        {
            int DumyValue = Input(i, j);
            OutPut(j2, i2) = DumyValue;
            i2++;
        }
        j2++;
    }

    return OutPut;
}

并不是说这完全忽略了使 slice 成为Matrix 方法的非常合乎逻辑的选择。虽然它是有道理的,但它不需要是一种方法,股票推荐是更喜欢一个免费的功能。一个很好的改进是使函数成为一个模板,以便它可以处理除了Matrix&lt;int&gt;之外的各种Matrix

最后,main 会发生什么?

int main()
{
    //Define a matrix for test:
    Matrix<int> Matrix2(4, 5, 1); // initialize matrix to all 1s
    int R = 4;
    int C = 4;
    Matrix<int> MatrixInput(R, C); // default initialize the matrix
    for (int i = 0; i < MatrixInput.getRows(); i++)
    {
        for (int j = 0; j < MatrixInput.getColumns(); j++)
        {
            int temp;
            temp = i ^ 2 + j ^ 2;
            // WARNING: ^ is XOR, not exponent. Maybe OP wants i XOR 2, but not
            // likely. But if XOR is the desired operation, there is a lurking
            // order of operation bug that needs to be addressed
            MatrixInput(i, j) = temp;
        }
    }

    std::cout << MatrixInput << '\n';
    std::cout << MatrixSlice(MatrixInput, 0, 3, 1, 1);

    return 0;
}

【讨论】:

    【解决方案2】:

    在你的代码中

    if (abs(Row1-Row2)>1 && abs(Col1-Col2)>1){
          vector<vector<int> > OutPut; 
          // OutPut dies here
      }else{
          vector<int> OutPut;
          // OutPut dies here 
      }
      // here is no OutPut
    

    OutPut 只存在于 IF 语句的末尾。

    您可以在没有 if 语句的情况下使用它,或者将所有使用它的代码添加到 if 语句中。

    【讨论】:

    • 这实际上看起来像是试图根据条件声明具有不同类型的变量。这显然行不通。
    • @VTT 是的,通过将 OutPut 移到它编译的 IF 语句之外。
    • 是的,如果我不使用 IF 会很好,但我需要根据切片的大小在 1D 和 2D 矢量之间切换。关于如何使用 IF 语句定义向量的任何建议?
    • @Alex 你有两个不同的对象,这意味着你必须以不同的方式处理它。因此,处理您的 OutPut 的所有代码都将转到 IF 语句。是的,它将被复制。因此,您将 IF 中的 for 循环移动到两个分支中。
    • @Alex 还考虑了该函数将返回什么。 return 0 对于一个听起来应该返回矩阵切片的函数来说似乎很奇怪。在这种情况下,复制代码是不够的,因为您将在返回vector&lt;int&gt; 还是vector&lt;vector&lt;int&gt;&gt; 时遇到问题。你不能同时返回。我一直坚持vector&lt;vector&lt;int&gt;&gt; 是最简单的解决方案,然后定义一个简单的Matrix 类。例如这里的 TwoDee 类:stackoverflow.com/a/32418684/4581301
    猜你喜欢
    • 1970-01-01
    • 2021-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多