9

有几种方法可以在 C++ 和 STL 中定义二维数组而无需内存操作,以下代码说明了两种不同的方法:

int main () 
{
    /**************
        1   2   3
        4   5   6
    ***************/
    // Method 1
    const int ROW = 2;
    const int COL = 3;
    int array1[ROW][COL];
    for(int i=0; i<ROW; i++)
        for(int j=0; j<COL; j++)
            array1[i][j] = i*COL+j+1;

    // Method 2
    typedef vector<vector<int> > ARRAY; 
    ARRAY array2;
    vector<int> rowvector;
    for(int i=0; i<ROW; i++)
    {
        rowvector.clear();
        for(int j=0; j<COL; j++)
            rowvector.push_back(i*COL+j+1);
        array2.push_back(rowvector);
    }
    return 0;
}

我的问题是:还有其他方法来定义二维数组吗?哪一个是最有效的?谢谢!

4

8 回答 8

19

在 C++11 中使用std::array

  std::array<std::array<int,3>,2> a {{
    {{1,2,3}},
    {{4,5,6}}
 }};

一些用法:

  a[0][2] = 13;
于 2012-10-11T16:29:26.490 回答
6

这里有很多取舍。

如果你声明一个 C 风格的 2D 数组int array[height][width],那么你真的会得到一个连续的内存块。编译器将索引转换为它们的一维地址

array[row][col] == *(array + row * width + col)
  • 优点:缓存一致性。所有的记忆都在同一个地方。
  • 缺点:每个索引都需要乘法。间接可能更快。

如果你使用 a vectorof vectors,那么每一行都是单独分配的。外部vector存储指向内部的指针vectors。索引变成间接加法:

array[row][col] == *(*(array + row) + col)
  • 优点:间接可能比乘法更快。
  • 缺点:缓存不一致,因为每一行都是单独分配的(除非实现优化vector<vector>)。

如果性能真的很重要,您需要测试两者并找出哪个对您的数据更快。

于 2012-10-11T14:01:00.987 回答
6

一种常见的模式是将二维数组封装在提供适当接口的类中。在这种情况下,您可以使用其他内部表示,例如单个rows*cols元素向量。接口(通常operator()(int,int)会将调用者的坐标映射到线性向量中的某个位置。

优点是它具有动态分配,但单一分配(与std::vector<std::vector<int>>每个向量必须获取其自己的内存不同)并且在单个块中提供数据的局部性。

于 2012-10-11T14:25:47.593 回答
6

定义数组的一种非常有效的方法是动态分配,使用newanddelete运算符。这是一个例子:

int **arr=new int*[ROW];
for( int i=0; i<ROW; ++i ) {
  arr[i] = new int[COL];
  for( int j=0; j<COL; ++j ) {
    arr[i][j] = some_val;
  }
}

这种方法的一大优点是,当您不再需要数组使用的内存时,您可以轻松删除它。以下是删除二维数组的示例:

for( int i=0; i<ROW; ++i ) {
  delete[] arr[i];
}
delete[] arr;   
于 2012-10-11T16:38:31.287 回答
4

要使用 声明二维数组std::vector,可以使用这种构造:

vector<vector<int> >  matrix( n, vector<int>(m, -1) );

这将创建一个matrix大小n为的 2D 数组m,所有元素都初始化为-1

它基本上是“使用值项初始化”nval构造函数的嵌套:

vector (size_type n, const value_type& val,
                 const allocator_type& alloc = allocator_type());

(从这里复制的构造函数定义)

于 2014-01-10T04:48:41.320 回答
4

还有其他方法来定义二维数组吗?

不显式地操作内存(malloc/free)。如果您使用静态分配数组(第一个示例),您会在编译时分配空间,因此您不能在运行时添加更多行或列。

第二个示例使用std::vector向您隐藏动态内存分配。这样,您最终可以在运行时添加更多行或列。

如果不需要动态修改数组维度,那么第一种解决方案是更简单更快的解决方案(即使我认为 std::vector 实现速度足够快,可以与静态数组相媲美,更优雅,更面向对象)。

如果您需要在运行时修改数组维度,请使用 std::vector,因为它使您免于直接处理 malloc 和 free。

于 2012-10-11T13:54:52.203 回答
0

如果您事先知道这些元素,那么您可以这样做

int arr[2][3] = {{1,2, 3}, {4, 5, 6}};

这应该比method1和method2更有效。使用向量,您不会自己进行内存操作,但向量实现可能会使用动态分配的数组。

于 2012-10-11T14:08:16.867 回答
-1

你可以像这个向量> m_2DArray;

然后,一旦您知道行数(行)和列数(列),您就可以调整二维数组的大小

m_2DArray.resize(行);

for(auto& el:m_2DArray) el.resize(columns);

您可以使用 m_2DArray[i][j] 访问二维数组中的数据,就像任何其他二维数组一样

于 2020-04-09T19:29:04.087 回答