使用 new for 2D 数组重写此 malloc

Rewrite This Malloc Using New For 2D Array

本文关键字:重写 malloc 数组 2D new for 使用      更新时间:2023-10-16

经过一些反复试验,我找到了一种方法来对 2D 数组进行 malloc 处理,使其在内存中是连续的,相当于非动态情况。

int numRows =2;
int numCols = 4;
int (*p)[numCols];
p    = (int (*)[numCols]) malloc(sizeof(int)*numRows*numCols);

所以 p 现在基本上与我所做的 int p[2][4] 相同 - 除了它在堆上而不是堆栈上。

2 问题:

  1. 我只需要调用 free(p) 来释放内存吗?没有循环?
  2. 我如何将其转换为使用新的,而不是 malloc?

我试过了

p = new (int (*)[4])[2];

但这给出了错误:

error: cannot convert int (**)[4] to int (*)[4] in assignment
下面是

一个类模板,它使用一个std::vector来保存连续的缓冲区,并使用大小感知的代理对象来逐维访问数组元素:

template<typename T>
class TwoDArray {
private:
    std::size_t n_rows;
    std::size_t n_cols;
    std::vector<T> buf;
public:
    class OneDArrayProxy {
    private:
        T *rowptr;
        std::size_t colsize;
    public:
        OneDArrayProxy(const T *rp, std::size_t cs) : rowptr(const_cast<T *>(rp)), colsize(cs) {}
        T const &operator[](std::size_t index) const {
            return rowptr[index];
        }
        T &operator[](std::size_t index) {
            return rowptr[index];
        }
        std::size_t size() const { return colsize; }
    };
    TwoDArray(std::size_t rows, std::size_t cols) : n_rows(rows), n_cols(cols), buf(rows * cols) {}
    TwoDArray() : TwoDArray(0, 0) {}
    OneDArrayProxy operator[](std::size_t index) const {
        return OneDArrayProxy(&buf[index * n_cols], n_cols);
    }
    std::size_t rows() const { return n_rows; }
    std::size_t columns() const { return n_cols; }
};

使用示例:

int main()
{
    TwoDArray<int> arr(9, 5);
    for (std::size_t i = 0; i < arr.rows(); i++) {
        for (std::size_t j = 0; j < arr.columns(); j++) {
            arr[i][j] = i * 10 + j;
        }
    }
    for (std::size_t i = 0; i < arr.rows(); i++) {
        // you can use the array element's 'size()' function instead of 'columns()'
        for (std::size_t j = 0; j < arr[i].size(); j++) {
            std::cout << arr[i][j] << " ";
        }
        std::cout << std::endl;
    }
}
你不能

在C++这样做。您的malloc()代码是完全有效的 C,但不是有效的C++。它不适用于new.

C++要求数组类型具有恒定大小,但 C 允许动态大小的数组类型。一维数组只有一个例外,可以在C++中以动态大小分配,但仅此而已。在 2D 数组中,第二个大小必须在编译时知道。

这是C比C++强大得多的一点。


说服g++在这方面遵循标准需要一点时间,但是编译这个小程序

#include <stdlib.h>
int main(int argc, char** args) {
    int (*foo)[argc];
}

g++ -pedantic -std=c++11 foo.cpp尽职尽责地生成错误消息:

foo.cpp: In function ‘int main(int, char**)’:
foo.cpp:4:17: warning: ISO C++ forbids variable length array ‘foo’ [-Wvla]

1)是的,你可以打电话给free()

请注意,您正在执行指针别名(指向不同类型的 2 个指针,int 和 int[] 具有相同的地址),这可能会导致细微的优化错误。 在C++使用malloc()是一种非常糟糕的做法,应该const numcols 。

2)在C++中执行此操作的方法是使用[<array>][2]如果在编译时知道大小:

     array<array<int, 4>,2> a;

更灵活的替代方法是使用允许动态大小和调整大小的向量:

     vector <vector <int>> b(2, vector<int>(4)); 

3)使用新的你也可以做:

    p = new (int[2][4]);

第一个维度也可以是可变的,但第二个维度必须是常量。 但我鼓励您使用标准的遏制器替代方案之一。