2014-12-11 3 views
0

Привет, я довольно новичок в C++, и мне нужно динамически выделять двумерный массив. Нет ошибок, но во время выполнения, когда я поставил в порядок и первый ряд, то я получаю сообщение об ошибке выполнения: «Segmentation Fault» ... Вот код:Динамическое распределение двумерного массива 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; 
} 
+2

Вы почти наверняка можете использовать 'vector >'. Гораздо менее сложно работать, поскольку нет головных болей выделения/освобождения. –

+0

'* arr =' должно быть 'arr [i] =' – 0x499602D2

+0

Да, но что, если я хочу использовать это? Мне просто нужно знать, что плохого в этом коде ... –

ответ

3

Вы забыли увеличиваем 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]; 

Кроме того, если ваш собирается изменить размеры одной из строк, метод выше является неэффективным по сравнению с этим способом выделения 2 копейки nsional массив:

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 NULL; // or rethrow the exception here 
    } 
    for(int i = 0;i < order; i++, pool += cols) 
     arr[i] = pool; 
    return arr; 
} 

Обратите внимание, что std::vector делает всю эту работу за вас. Однако, если по какой-то причине вы не можете использовать вектор, а двухмерный массив останется на одном уровне в течение всего его жизненного цикла, используйте вторую форму.

Кроме того, второй способ уменьшает фрагментацию памяти кучи. Вместо вызовов rows в распределитель, для распределения данных распределитель выделяет только один вызов. Если rows были, скажем, 1000 или 10000, вы сразу увидите, что лучше сделать 2 звонка на new[] вместо 10 000 звонков на new[].

+1

Спасибо, это то, чего я хочу. : D –

1

Заменить

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

В вашем настоящем коде инициализации только первый элемент массива.

Смежные вопросы