繁体   English   中英

如何在没有内存操作的情况下在 C++ 和 STL 中定义二维数组?

[英]How to define a 2D array in C++ and STL without memory manipulation?

在 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;
}

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

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

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

一些用法:

  a[0][2] = 13;

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

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;   

这里有很多权衡。

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

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

如果您使用vectorvectors ,则每一行都单独分配。 外部vector存储指向内部vectors指针。 索引变成一个间接加法:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

如果你事先知道元素,那么你可以做

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

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

你可以像这样 vector> m_2DArray;

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

m_2DArray.resize(rows);

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM