如何在C++中动态分配连续的二维数组?



我需要在垃圾 API 中使用 2d 字符数组,该数组绝对需要使用数组而不是向量(非常强调这一点,因为我所有的搜索都有答案"使用向量"。我希望我能)。

我认为这样做的方法是分配一个大小行 * 字符长度的外部数组,而不是这样做:

char** arr;
arr = new char*[100];
// for loop that allocates the internal arrays

但我不确定我需要使用什么方法来使其连续?我是否需要先分配一个庞大的一维数组,然后将一维数组分块分配给二维数组?

正如其他答案所说:分配n * m条目来创建连续数据,然后可以将其包装在指针中以创建 2D 数组。

。绝对需要使用数组而不是向量...

我不确定vector是基于正在使用的 API 还是要求的约束——但值得注意的是,vector可用于实现的内存管理——同时仍然使用原始数据(可以通过&vec[0]vec.data()访问),它返回指向数组第一个元素的指针, 并且可以与接受原始指针的函数一起使用)。

由于这个问题是关于 c++ 的,因此一种选择是将n * m数组包装在一个class中,该数组的作用类似于二维数组,但实际上是连续的。

一个简单的例子可以是:

class array_2d
{
public:
array_2d( std::size_t rows, std::size_t columns )
: m_rows(rows), m_cols(columns), m_array( new char[rows * columns] )
{
}
~array_2d()
{
delete [] m_array;
}
// row-major vs column-major is up to your implementation
T& operator()( std::ptrdiff_t row, std::ptrdiff_t col )
{
// optional: do bounds checking, throw std::out_of_range first
return m_array[row * m_cols + col];
// alternatively:
// return m_array[col * m_rows + row];
}
// get pointer to the array (for raw calls)
char* data()
{
return m_array;
}
private:
char* m_array; 
std::size_t m_rows;
std::size_t m_cols;
};

(理想情况下,char*std::unique_ptr<char[]>std::vector<char>以避免内存泄漏情况,但既然你说vector不可行,我写这个最少)

这个例子重载了调用运算符(operator())——但这也可以是一个命名函数,如at(...);选择权取决于你。然后,此类类型的使用将是:

auto array = array_2d(5,5); // create 5x5 array
auto& i01 = array(0,1); // access row 0, column 1

(可选)如果[][]语法对于表现得像 2D 数组(而不是(r,c)语法)很重要,则可以从对重载operator [](未经测试)的调用中返回代理类型:

class array_2d_proxy
{
public:
array_2d_proxy( char* p ) : m_entry(p){}
char& operator[]( std::ptrdiff_t col ){ return m_entry[col]; }
private:
char* m_entry;
};
class array_2d
{
...
array_2d_proxy operator[]( std::ptrdiff_t row )
{
return array_2d_proxy( m_array + (row * m_cols) );
}
...
};

这将允许您拥有"正常"的 2D 数组语法,同时仍然是连续的:

auto& i00 = array[0][0];

这是一个很好的方法:

void array2d(int m, int n) {
std::vector<char>  bytes(m * n);
std::vector<char*> arrays;
for (int i = 0; i != m * n; i += n) {
arrays.push_back(bytes.data() + i);
}
char** array2d = arrays.data();
// whatever
}

C++"具有可变列长度的连续二维数组"的主要问题是,像myArray[r][c]这样的访问要求编译器在编译时知道myArray类型的列大小(与 C 不同,C++不支持可变长度数组 (VLA))。

为了解决这个问题,您可以分配一个连续的字符块,并另外创建一个指针数组,其中每个指针都指向一行的开头。有了这样的"视图",您可以使用myArray[r][c]表示法间接寻址连续的内存块:

int main() {
// variable nr of rows/columns:
int rows = 2;
int columns = 5;
// allocate continuous block of memory
char *contingousMemoryBlock = new char[rows*columns];
// for demonstration purpose, fill in some content
for (int i=0; i<rows*columns; i++) {
contingousMemoryBlock[i] = '0' + i;
}
// make an array of pointers as a 2d-"view" of the memory block:
char **arr2d= new char*[rows];
for (int r=0; r<rows;r++) {
arr2d[r] = contingousMemoryBlock + r*columns;
}
// access the continuous memory block as a 2d-array:
for (int r=0; r<rows; r++) {
for (int c=0; c<columns; c++) {
cout << arr2d[r][c];
}
cout << endl;
}
}

最新更新