【问题标题】:How to pass two-dimensional array as an argument?如何将二维数组作为参数传递?
【发布时间】:2011-06-15 17:14:05
【问题描述】:

我的Matrx 类被定义为

class Matrx
{
 double A[50][50];
 int m,n;
public:
 Matrx(void);
 Matrx(int a, int b)
 {
  m=a;
  n=b;
 }
 Matrx operator +(Matrx b);
 Matrx Transpose(Matrx b);
 Matrx operator *(Matrx b);
 CString printMatrx();
 void readMatrx(double a[][]);
 Matrx TransposeMat(Matrx b);
};

void Matrx::readMatrx(double a[][])
{
 for(int i=0;i< m;i++)
  {
   for(int j=0;j< n;j++)
    A[i][j]=a[i][j];
  }
}

智能感知会出现如下错误

1 IntelliSense:数组可能没有这种类型的元素 d:\bmadaptive_dd_v1.02\matrx.h 17 27 TestServer

为什么?

如何将二维数组作为函数的参数传递?

【问题讨论】:

  • 虽然您提供的代码不是有效的 C++,但不要依赖 Intellisense 来查找语法错误。 Intellisense 是一个自动完成工具,而不是语法检查器。它只会“快速查看”您的代码,可能不会给出最准确的错误消息。您应该尝试编译它(当然使用实际的编译器)并逐字发布实际的编译器错误消息(如果有)。
  • 我确信围绕这个有很多重复和问题。在上面的框中搜索[c++] bidimensional array 或类似内容,然后查看不同的问题/答案。即使它们不完全相同,它们也一定会提供一些见解。

标签: c++ arrays multidimensional-array


【解决方案1】:

问题是在C++中传递多维数组作为参数时,必须指定最外层数组的维度。例如:

void ThisIsIllegal(int arr[][]); // Wrong!
void ThisIsAlsoIllegal(int arr[10][]); // Also wrong
void ThisIsLegal(int arr[][10]); // Okay

如果您希望能够拥有一个接收任意大小数组的函数,您可以使用模板:

template <size_t N, size_t M>
void ThisIsAlsoLegal(int (&arr)[M][N]);

最后一个版本接受任何正确类型的多维数组,并且可能是您正在寻找的。​​p>

【讨论】:

  • class Matrx { ----------------------template void readMatrx(double (&a)[M ][N]);矩阵转置矩阵(矩阵 b); };我已经改变了我的类和我的函数,比如 template void Matrx::readMatrx(double a[M][N]) { for(int i=0;i
  • "...您必须指定除最内层以外的所有维度" 以推广到所有数组(包括单个维度),否则我建议使用 ThisIsAlsoLegal。
  • @user543265- 你更新了类主体中的函数声明了吗?
  • 非常巧妙地使用原始模板参数值。 :)
  • 在这种情况下,您似乎对“最外层”有一个有趣的定义。我会说“最里面”。
【解决方案2】:

你很幸运,那么因为:

for(int j=0;j<m;j++)
    A[i][j]=0.0;

应该是:

for(int j=0;j<**n**;j++)
    A[i][j]=0.0;

【讨论】:

    【解决方案3】:

    感谢你们所有人...你们真的帮了大忙...我发现自己的类的新定义和矩阵的函数定义符合我的需要。我需要您对此发表评论...下面是类声明的示例..

    #include<iostream>
    #include"stdafx.h"
    using namespace std;  
    const int M=100; const int N=100;  
    class Matrix  
    {  
        double A[M][N];  
        int m,n;  
    public:  
        Matrix(void);  
        Matrix(int a, int b)  
        {  
            m=a;  
            n=b;  
            for(int i=0;i<m;i++)  
            {  
                for(int j=0;j<m;j++)  
                    A[i][j]=0.0;  
            }  
        }  
        Matrix operator +(Matrix b);  
        Matrix operator -(Matrix b);  
        Matrix operator *(Matrix b);  
        void TransPose(Matrix b);  
        CString printMatrix();  
        void readMatrix(double*);  
    };
    

    然后是函数实现

    #include "stdafx.h"
    #include "Matrix.h"
    
    Matrix::Matrix(void)  
    {  
    }  
    
    Matrix Matrix::operator *(Matrix b)  
    {  
     Matrix c(m,m);  
     if(n!=b.m)  
     {  
        HWND hndOwner(0);   
        MessageBoxW(hndOwner,L"Multiplication not possible row and column does not match",L"Error",NULL);  
        Matrix errMat(1,0);  
        double er[1][1]={0}; errMat.readMatrix((double *)er);  
        return errMat;  
     }  
    for(int i=0;i< m;i++)  
    {  
    for(int k=0;k< m;k++)  
    {  
    c.A[i][k]=0;  
    for(int j=0;j< n;j++)  
    {  
    c.A[i][k] = c.A[i][k]+(A[i][j] * b.A[j][k]) ;  
    }  
    }  
    }  
    return c;  
    }  
    Matrix Matrix::operator +(Matrix b)  
    {  
        Matrix c(m,n);  
        if((n!=b.n)||(m!=b.m))  
     {  
        HWND hndOwner(0);   
        MessageBoxW(hndOwner,L"Addition not possible row and column does not match",L"Error",NULL);  
        Matrix errMat(1,0);  
        double er[1][1]={0}; errMat.readMatrix((double *)er);  
        return errMat;  
     }  
        for(int i=0;i<m;i++)  
            {  
                for(int j=0;j< n;j++)  
                    {  
                        c.A[i][j]=0.0;  
                    }  
            }  
            for(int i=0;i< m;i++)  
            {  
                for(int j=0;j< n;j++)  
                    {  
                        c.A[i][j]=A[i][j]+b.A[i][j];  
                    }  
            }  
    return c;  
    }    
    CString Matrix::printMatrix()  
    {  
        CString strB(" "),strDisp;  
        for(int iRow=0;iRow<m;iRow++)  
        {  
            for(int iColumn=0;iColumn<n;iColumn++)  
            {  
                strB.Format(L"%lf ",A[iRow][iColumn]);  
                strDisp+=strB;  
            }  
                strDisp+="\r\n";  
        }  
            return strDisp;  
    }  
    void Matrix::readMatrix(double *ptrarr)  
    {  
        for(int i=0;i< m;i++)  
            {  
                for(int j=0;j< n;j++)  
                    A[i][j]=*(ptrarr+i*n+j);  
            }  
    }  
    void Matrix::TransPose(Matrix b)  
    {  
        for(int i=0;i<b.n;i++)  
        {  
            for(int j=0;j<b.m;j++)  
                A[i][j]=b.A[j][i];  
        }  
    }   
    

    上面的简单代码到目前为止运行良好...如果您有任何改进建议,请提出..

    【讨论】:

      【解决方案4】:

      您需要正确了解数组和指针。这包括“嗯!它们没有我想象的那么有用”这一课。在您熟悉了数组和指针的确切工作原理之后,您应该重新考虑您的设计。

      例如,在我看来,以下设计有很多优点:

      #ifndef MATRIX_HPP_INCLUDED
      #define MATRIX_HPP_INCLUDED
      
      #include <vector>
      #include <algorithm>
      
      class matrix
      {
      public:
          typedef std::vector<double>::size_type st;
          matrix() : rows_(0), cols_(0) {}
          matrix(int r, int c) : rows_(r), cols_(c), coeffs_(st(r)*c,0.0) {}
          void reset(int r, int c)
          { rows_=r; cols_=c; coeffs_.clear(); coeffs_.resize(st(r)*c,0.0); }
          int rows() const {return rows_;}
          int cols() const {return cols_;}
          double const& operator()(int i, int j) const {return coeffs_[indexof(i,j)];}
          double      & operator()(int i, int j)       {return coeffs_[indexof(i,j)];}
          double const* operator[](int i) const {return &coeffs_[indexof(i,0)];}
          double      * operator[](int i)       {return &coeffs_[indexof(i,0)];}
          void swap(matrix& that)
          {
            std::swap(this->rows_,that.rows_);
            std::swap(this->cols_,that.cols_);
            this->coeffs_.swap(that.coeffs_));
          }
      private:
          int rows_, cols_;
          std::vector<double> coeffs_;
          st indexof(int i, int j) const {return st(i)*cols+j;} // row major storage
      };
      
      inline void swap(matrix& a, matrix& b) {a.swap(b);}
      
      matrix& operator+=(matrix& lhs, matrix const& rhs);
      matrix operator+(matrix const& lhs, matrix const& rhs);
      matrix operator*(matrix const& lhs, matrix const& rhs);
      inline matrix& operator*=(matrix& lhs, matrix const& rhs)
      { matrix tmp = lhs * rhs; swap(tmp,lhs); return lhs; }
      ...
      
      #endif
      

      这样您就不会为小矩阵浪费任何空间,并且可以支持大矩阵。此外,使用 std::vector 代替指向动态分配内存的指针成员无需定义自己的复制构造函数、赋值运算符和析构函数。

      当然,您可以使用 boost::multi_array 作为矩阵替换,但使用自定义矩阵类允许您在自己的命名空间中声明重载运算符,这是由于 ADL(参数相关查找)而需要的。

      您可能认为这并不能真正回答您的问题。在这种情况下,让我强调一下,我认为您并不完全了解数组和指针的工作/行为方式。这是您应该在一本像样的 C++ 书籍中查找的内容。一个人可以写很多关于这个主题的页面。你不能期望看到一个简短的答案来解释所有的怪癖。

      查看Definite C++ Book Guide 线程。

      【讨论】:

      • 谢谢sellibitze...你是对的...请告诉我现在是否必须重载+、*、/,-我是否必须像以前一样单独编写重载函数?如果是,请在课堂上说明您提供的声明...
      • 另外,最好使用像boost::multi_array 这样的标准,而不是重新实现。
      • sellibitze 你能告诉我除了 iostream.h 和使用 namspace std 编写之外,我还需要包含任何特殊的头文件吗?因为我收到错误为 15 IntelliSense: namespace "std" has no member "vector" d:\bmadaptive_dd_v1.02\matrx.h 10 19 TestServer
      • @user543265: std::vector&lt;&gt;&lt;vector&gt; 标头中声明。另外,你不应该在头文件中写using namespace std;
      【解决方案5】:

      您可以指定所有维度或仅指定最后一个维度来传递数组:

      void Matrx::readMatrx(double a[][50])
      {
       for(int i=0;i< m;i++)
        {
         for(int j=0;j< n;j++)
          A[i][j]=a[i][j];
        }
      }
      

      【讨论】:

      • 您不能将二维数组作为指向指针的指针传递。多维数组不是指针数组!
      • 这是一个常见错误。二维数组是一个连续的内存块,其中第一行的所有元素后面跟着第二行,依此类推。如果二维数组衰减,它通过转换为指向第一个元素的指针来实现,该元素将是array of N elements of type T,而不是pointer to T。在访问 row 数组之前,它将再次衰减为一个指针,而第二个指针将具有数组的地址。即:&amp;array&amp;array[0]&amp;array[0][0]是同一个地址。
      • 另一方面,使用pointer to pointer to T,存储的第一个元素的数组将是取消引用第一个指针p[0]的结果,将其解释为指针并再次取消引用(p[0])[0] , 除非它已经用自己的地址初始化,否则它将不同于 &amp;p[0][0]
      • 哦,对不起。我知道了。这是错误的例子。在其他情况下,我使用了指向指针的指针,并认为它可能会起作用。我会更正答案。
      【解决方案6】:

      您需要指定除第一个维度之外的所有维度,例如

      void Matrx::readMatrx(double a[][50])
      

      从这里你应该能够看到你实现类的方式存在根本问题,但至少你现在应该能够编译代码。

      【讨论】:

      • 谢谢保罗....它工作但现在收到这样的错误消息。 5 IntelliSense:“double ()[4]”类型的参数与“double ()[50]”类型的参数不兼容 d:\bmadaptive_dd_v1.02\testserverdlg.cpp 1041 19 TestServer for the代码双 X[15][4],splusn[15],m_dC=1.0,y[15],W[15][4],WTrans[4][15];矩阵 Wtest(15,4),WtestTrans(4,15); for(int r=0;r
      • @user543265:在没有编译器标记的代码的情况下编写编译器错误并不太有用。在评论中这样做会使阅读变得更加困难。要么更新将其添加到末尾的问题,要么创建一个单独的问题。任何一种都会让人们更容易提供帮助。
      猜你喜欢
      • 2020-10-04
      • 2020-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-29
      • 2015-06-23
      相关资源
      最近更新 更多