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

Posted

技术标签:

【中文标题】二维数组C++的动态分配【英文标题】:Dynamic Allocation of two-dimensional array C++ 【发布时间】:2015-02-10 01:42:30 【问题描述】:

您好,我是 C++ 新手,我需要动态分配二维数组。没有错误,但在运行时,当我设置订单和第一行时,我得到一个运行时错误:“Segmentation Fault”......这是代码:

#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;

【问题讨论】:

使用vector&lt;vector&lt;double&gt;&gt; 几乎肯定会更好。使用起来不那么复杂,因为没有分配/释放问题。 *arr = 应该是arr[i] = 是的,但如果我想使用它怎么办?我只需要知道这段代码有什么不好... 不应该使用它的一个原因是没有检查 new[] 是否在该循环中的任何地方失败。如果失败,则由于new[] 抛出异常而导致内存泄漏。 好的,所以我只需要使用这个:arr[i] 还是总是使用向量? 【参考方案1】:

您忘记在初始化循环中增加 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 会为您完成所有这些工作。但是,如果由于某种原因您不能使用向量,并且二维数组在其整个生命周期中将保持相同的大小,请使用第二种形式。

另外,第二种方法减少了堆的内存碎片。代替rows 调用分配器,只调用分配器来分配数据。如果 rows 是 1,000 或 10,000,您会立即看到最好对 new[] 进行 2 次调用,而不是对 new[] 进行 10,000 次调用。

【讨论】:

谢谢,这就是我想要的。 :D【参考方案2】:

替换

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];

在您当前的代码中,您只初始化第一个数组元素。

【讨论】:

以上是关于二维数组C++的动态分配的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C++ 中的指针动态分配和解除分配二维数组?

需要有关 C++ 中二维数组的动态内存分配的帮助

C++:使用迭代器构造一个二维动态分配的数组

在 C++ 中使用动态内存分配创建二维数组

指向 C++ 中动态分配的二维数组中的一行的指针

C++建立动态二维数组