C风格的2D动态数组,只需要执行一次free()操作

时间:2017-08-01 20:06:57

标签: c++ arrays pointers

我想构建2D数组而无需执行许多free()操作。

#include <iostream>
#define un unsigned
#define ln long

un ln ** array_builder(un ln rows, un ln cols)
{
    register const un ln row_memory = cols * sizeof(un ln);
    auto array = (un ln **) malloc( rows * ( sizeof(un ln *) + row_memory ) );

// First line: The bytes of memory required to store a single row in the array
// Second line: We want to store all the pointers in the single array

    auto pointer = (void *) array[0];  // sizeof(void *) == 1. It is convenient for our purposes
    pointer += rows * sizeof(un ln *);  /* Thus we skip the first pointers in the array (their amount equals 'rows').
                                       This space is considered to store pointers of array[row] type */

    for (un ln int i = 0; i < rows; i++)
    {
        array[i] = (un ln *) pointer;  // We write pointers to each row in the array[row]
        pointer += row_memory;
    }

    return array;
// We've built 2D-array. Now we can access to the elements of this array by convenient way as array[row][col]
// Don't forget to free(array) after use
}

但是这个程序工作不正确。例如,当我尝试通过数组[row] [col] = some_value更改某个值时,每次都会使程序在不同的地方崩溃。

3 个答案:

答案 0 :(得分:3)

在C ++中,不使用malloc和free,也不使用等效的new和delete。一个人会使用正确的RAII,即没有手动释放资源。 对于二维数组,可以使用如下的单个字段:

std::vector<int> data;
data.resize(width * height);

//in case you know the amount of data at compile time use a static sized field
std::array<int, width * heigth> data;

//access a single cell
int cell = data[y * width + x];

//or obtain a pointer to a row of cells
int *rowptr = &data[y * width];
int cellinrow = rowptr[x];

这比分配多行更节省空间和时间。

在C中,您可以使用malloc等效地分配单个int块或使用静态大小的int [width * height]数组;

请注意,不要混用C和C ++,也不要使用register关键字,也不要使用lazy #defines

答案 1 :(得分:0)

你做不到。编译器需要知道要返回的类型,这需要内部数组的大小。另外,无论如何你都无法返回数组。

你能做的就是做一个为你做的课。你可以称之为vector或其他东西。让它负责分配和解除分配某种类型的动态数组...然后将一个放在另一个内部,如下所示:

vector<vector<unsigned long>> {rows, vector<unsigned long>{cols,0}};

如果您仔细阅读Internet上的C ++教程和参考资料,您可能会发现某人已经写过这样的内容。

答案 2 :(得分:0)

假二维数组的算法unsigned long ** - 指向unsigned long的指针

分配需要

1)指针数组array有足够的内存 2)可能有一些填充用于unsigned long的对齐 3)对rows*cols

unsigned long记忆

这可以通过1次分配完成,因此只需要1 free()

指定array元素以指向分配的第3部分。请记住对齐要求。

不清楚C ++代码为什么会这样。

OP的方法类似,但缺乏对齐考虑因素。如果指针窄于unsigned long或在其他情况下,这可能会导致代码崩溃。

-

一些未经测试的C ++代码以&#34; C-style&#34;的方式使用malloc()

typedef unsigned long data_t;

data_t **alloc_2Ddata(size_t rows, size_t cols) {
  data_t **a;
  size_t row_ptrs_size = sizeof *a * rows;
  size_t data_size = sizeof **a * rows * cols;
  size_t pad = (sizeof **a - row_ptrs_size % sizeof **a) % sizeof **a;
  a = (data_t **) malloc(row_ptrs_size + pad + data_size);
  if (a) {
    data_t *data = (data_t*) (((char*) a) + row_ptrs_size + pad);
    for (size_t r = 0; r < rows; r++) {
      a[r] = data;
      data += cols;
    }
  }
  return a;
}