二维数组C++的动态分配

Dynamic Allocation of two-dimensional array C++

本文关键字:动态分配 C++ 二维数组      更新时间:2023-10-16

嗨,我对C++很陌生,我需要动态分配二维数组。没有错误,但在运行时,当我设置订单和第一行时,我收到运行时错误:"分段错误"......代码如下:

#include <iostream>
using namespace std;
double ** allocateDynamicArray(int &order){
    double ** arr = new double *[order];
    for(int i = 0;i < order; i++){
            *arr = new double[order+1];
    }
    return arr;
}
void deallocateDynamicArray(double **arr, int order){
    for(int i=0; i<order; i++){
        delete [] arr[i];
    }
    delete [] arr;
}
void addAndPrintArray(double **arr, int order){
    cout << "Zadejte prvky pole radu " << order << endl;
    for(int i=0; i< order; i++){
        for(int j=0; j< order+1; j++){
            cout << "Pole[" << i << "][" << j << "]: ";
            cin >> arr[i][j];
        }
    }
    for(int i=0; i< order; i++){
        for(int j=0; j< order+1; j++){
            cout << arr[i][j] << " ";
            if(arr[i][j] < 10 && arr[i][j] > -10){
                cout << " ";
            }
            cout << endl;
        }
    }
}
int main()
{
    int order;
    cin >> order;
    double **dynArray = allocateDynamicArray(order);
    addAndPrintArray(dynArray, order);
    deallocateDynamicArray(dynArray, order);
    return 0;
}

您忘记在初始化循环中递增arr

for(int i = 0;i < order; i++){
     *arr = new double[order+1];

请改为执行以下操作:

for(int i = 0;i < order; i++){
     arr[i] = new double[order+1];

此外,除非您要更改其中一行的维度,否则与分配二维数组的方式相比,上述方法效率低下:

double ** allocateDynamicArray(int &order){
    double ** arr = new double *[order];
    int cols = order+1;
    double *pool = new double [order * cols];
    for(int i = 0;i < order; i++, pool += cols){
           arr[i] = pool;
    }
    return arr;
}
void deallocateDynamicArray(double **arr){
        delete [] arr[0];
        delete [] arr;
    }

只需调用两次new[],只需调用两次delete[],无论行数和列数如何。

上述第二种形式应该优先于第一种形式的另一个原因是new[]可能会引发异常。

使用第一种形式,如果在该循环中的某个地方,new[]抛出异常,您必须跟踪所有以前的成功分配,并通过发出delete[]调用来"回滚它们"。 不好。

使用第二种形式,如果对new[]的第一次调用失败,则没有害处,因为将抛出异常而不会泄漏(因为没有成功分配内存(。 如果对new[]的第二次调用失败,您需要做的就是(在catch块内(删除对new[]的第一次调用。

double ** allocateDynamicArray(int &order) {
    double ** arr = new double *[order];
    int cols = order+1;
    try {   
       double *pool = new double [order * cols];
    }
    catch (std::bad_alloc& e)
    {
       delete [] arr;  // delete previous allocation
       return nullptr;  // or rethrow the exception here
    }
    for(int i = 0;i < order; i++, pool += cols)
        arr[i] = pool;
    return arr;
}

请注意,std::vector为您完成所有这些工作。 但是,如果由于某种原因不能使用 vector,并且二维数组在其整个生命周期中将保持相同的大小,请使用第二种形式。

此外,第二种方法减少了堆的内存碎片。 不是对分配器进行rows调用,而是只对分配器进行一次调用来分配数据。 如果是rows,比如说 1,000 或 10,000,您马上看到最好对new[]进行 2 次调用,而不是向new[]拨打 10,000 次电话。

替换

double ** arr = new double *[order];
for(int i = 0;i < order; i++){
        *arr = new double[order+1];

double ** arr = new double *[order];
for(int i = 0;i < order; i++){
        arr[i] = new double[order+1];

在现有代码中,您只初始化第一个数组元素。