C++ 以优雅的方式创造&;在c+中传递多维数组+;?

C++ 以优雅的方式创造&;在c+中传递多维数组+;?,c++,pointers,multidimensional-array,C++,Pointers,Multidimensional Array,第一个问题: 对于已知维度,我们不需要new/malloc进行创建 const int row = 3; const int col = 2; int tst_matrix[row][col] ={{1,2},{3,4},{5,6}} 然而,将这个二维数组传递给另一个函数并不容易,对吗?因为 int matrix_process(int in_matrix[][]) 如果不合法,则必须指定除第一个尺寸外的所有尺寸。如果我需要更改in_矩阵的内容,如何轻松地将t

第一个问题:

对于已知维度,我们不需要new/malloc进行创建

   const int row = 3;  
   const int col = 2;  
   int tst_matrix[row][col] ={{1,2},{3,4},{5,6}}
然而,将这个二维数组传递给另一个函数并不容易,对吗?因为

   int matrix_process(int in_matrix[][])
如果不合法,则必须指定除第一个尺寸外的所有尺寸。如果我需要更改in_矩阵的内容,如何轻松地将tst_矩阵传递给函数矩阵_过程

第二个问题: 用C++创建二维数组的标准方法是什么?我不想使用std::vector等。。在这里 这就是我想到的,这是最好的方法吗

    int **tst_arr = new int*[5];
    int i=0, j=0;

    for (i=0;i<5;i++)
    {
       tst_arr[i] = new int[5];
       for (j=0;j<5;j++)
       {
          tst_arr[i][j] = i*5+j;
       }
    }
int**tst_arr=newint*[5];
int i=0,j=0;

对于(i=0;i多维数组,如果所有边界在运行时都是可变的,我所知道的最常见的方法是使用动态分配的一维数组,并“手动”进行索引计算在C++中,通常使用一个类,如<代码> STD::vector < /Cl>专业化,管理这个数组的分配和分配。

这与固定边界的多维数组的布局基本相同,没有任何固定的开销,任何方法都需要在运行时将数组中的所有条带传递到运行时。

< P>我认为最好的办法是避开原始的C++数组,而不是包装类。multi_数组类型。这消除了原始数组中出现的各种奇怪现象(难以将它们的参数传递给函数,跟踪数组大小的问题,等等)

另外,我强烈建议您重新考虑一下您对std::vector的立场。它比原始数组安全得多,因此在大多数情况下,在向量上使用动态数组并不是一个很好的理由。如果您有C背景,那么花时间进行切换是值得的。

1)

template
二等舱{
公众:
静态常量大小\u t行=行;
静态常量大小=列;
/* ... */
T在[行][Col];
};
模板
int矩阵_过程(T&in矩阵){
在[0][0]处的_矩阵中返回T::Row*T::Col+;
}

2) 使用std::vector。您正在添加一些函数调用(可能在优化的构建中内联),并且可能正在导出一些额外的符号。我想有很好的理由来避免这种情况,但适当的理由是非常罕见的。简单的答案是,C++中的优雅方法(你标记C和C++,但是你的代码是C++ <代码>新的< /代码> /<代码>删除< /代码>)是通过创建一个二维类并通过引用(或引用)来传递。在那之后,下一个选项应该始终是
std::vector
(同样,我将根据向量实现矩阵类)。除非您有非常令人信服的理由,否则我将避免处理原始数组

如果确实需要,但只有在确实需要的情况下,才可以完美地使用多维数组,这比使用普通数组要麻烦一些。如果所有维度在编译时都是已知的,就像在第一个块中一样,这是一些选项

const unsigned int dimX = ...;
const unsigned int dimY = ...;
int array[dimY][dimX];
void foo( int *array[dimX], unsigned int dimy ); // [1]
void foo( int (&array)[dimY][dimX] );            // [2]
在[1]中,通过使用
按值传递
语法,数组将衰减为指向第一个元素的指针,这意味着指向
int[dimX]
的指针,这就是您需要传递的内容。请注意,您应该在另一个参数中传递另一个维度,因为函数中的代码不知道这一点。在[2]中,通过向数组传递一个引用,所有维度都是固定的和已知的。编译器将确保仅使用适当大小的数组(两个维度一致)调用,因此无需传递额外的参数。第二个选项可以模板化,以适应不同的大小(所有大小都在编译时已知):

模板
void foo(整数和数组)[DimY][DimX]);
编译器将扣除大小(如果将实际数组传递给模板),您将能够在模板内使用它作为
DimX
DimY
。这允许使用具有不同数组大小的函数,只要它们在编译时都是已知的

如果在编译时不知道维度,那么事情就会变得非常混乱,唯一明智的方法就是将矩阵封装在一个类中。基本上有两种方法。第一种方法是分配一个连续的内存块(就像编译器在前面的例子中所做的那样),然后提供按二维索引该块的函数。查看第一段中的链接,了解一种简单的方法,即使我会在内部使用
std::vector
而不是原始指针。请注意,对于原始指针,您需要在销毁时手动管理指针的删除,否则您的程序将泄漏内存

另一种方法,也就是你在问题的第二部分中开始的方法,是我无论如何都要避免的方法,它包括将一个指针保存到一个整数指针块中。这使内存管理变得复杂(您从必须删除一个指针变成必须删除
DimY+1
指针——每个
array[i]
,再加上
array
),并且您还需要在分配期间手动保证所有行包含相同数量的列。可能出现错误而没有收益的事情的数量大幅增加,但实际的损失(保存中间指针所需的内存更多,运行时性能更差,因为您必须重复引用,数据的局部性可能更差

包装:编写一个类,以连续内存块的形式封装二维对象(数组,如果编译时大小已知--为不同的编译时大小编写模板--,
std::vector
如果直到运行时才知道大小,则仅当
    #include <iostream>

    using namespace std;

    //Input Matrix--a: Array[M][N]

    int change_row_col( int **a)
    {
     int i,j;
     int* row = new int[5];
     int* col = new int[5];

     //initialization
     for(i=0;i<5;i++)
     {
        row[i]=0;
     }

     for(j=0;j<5;i++)
     {
        col[j]=0;
     }

     //check which element is 0
     for (i=0; i<5; i++)
         for(j=0;j<5;j++)
        {
           if (*(*(a+i)+j)==0)  //why I can not use a[i][j] here?
           {
               row[i]=1;
               col[j]=1;              
           }
        }

     for(i=0;i<5;i++)
       for (j=0;j<5;j++)
       {
            if (row[i] || col[j])    
            {
               *(*(a+i)+j)=0;
            }
       }
     return 1;
 }



int main ()
{
    int **tst_arr = new int*[5];
    int i=0, j=0;

    for (i=0;i<5;i++)
    {
       tst_arr[i] = new int[5];
       for (j=0;j<5;j++)
       {
          tst_arr[i][j] = i*5+j;
       }
    }

  for (i=0; i<5;i++)
  {
    for(j=0; j<5;j++)
    {
       cout<<" "<<tst_arr[i][j];
    }
    cout<<endl;
  }
 change_row_col(tst_arr);

 for (i=0; i<5;i++)
 {
     for(j=0; j<5;j++)
     {
        cout<<" "<<tst_arr[i][j];
     }
     cout<<endl;
 }

   for (i=0;i<5;i++)
   {
      delete []tst_arr[i];
   }
   delete []tst_arr;
 }
template < typename T, size_t Row_, size_t Col_>
class t_two_dim {
public:
    static const size_t Row = Row_;
    static const size_t Col = Col_;
    /* ... */
    T at[Row][Col];
};

template <typename T>
int matrix_process(T& in_matrix) {
    return T::Row * T::Col + in_matrix.at[0][0];
}
const unsigned int dimX = ...;
const unsigned int dimY = ...;
int array[dimY][dimX];
void foo( int *array[dimX], unsigned int dimy ); // [1]
void foo( int (&array)[dimY][dimX] );            // [2]
template <unsigned int DimX, unsigned int DimY>
void foo( int (&array)[DimY][DimX] );
template<size_t M,size_t N>
void Fun(int (&arr)[M][N])
{
   for ( int i = 0 ; i < M ; i++ )
   {
       for ( int j = 0 ; j < N ; j++ )
       {
           /*................*/
       }
   }
}
void editArray(int M,int N,int matrix[M][N]){

//do something here

}
int mat[4][5];

editArray(4,5,mat);  //call in this way