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

问题描述 投票:1回答:2

嗨,我是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;
}
c++ arrays dynamic multidimensional-array allocation
2个回答
4
投票

您忘记在初始化循环中增加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次呼叫。


2
投票

替换

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

with

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

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

© www.soinside.com 2019 - 2024. All rights reserved.