Функция создания двумерного динамического массива. С++

Пытаюсь создать функцию типа void для создания двумерного динамического массива и создать в функции main какой-нибудь указатель для быстрого доступа к этому двумерному массиву, в итоге получаю кучу ошибок. Понимаю, что легче было бы это сделать через тот же тип double, но мне уже интересно, возможно ли это через void?

using namespace std;
void Array(unsigned int rows, unsigned int colms)
{
    double** array2d = new double* [rows];
    for (unsigned int i = 0; i < rows; i++)
        array2d[i] = new double[colms];     
}

int main()
{

    // 1. Создание двумерного массива
    unsigned int numRows = 4;
    unsigned int numCols = 10;
    void (*list)(unsigned int, unsigned int) = Array;

    // 2. Инициализация двумерного массива
    int data = 0;
    for (unsigned int i = 0; i < numRows; i++)
    for (unsigned int j = 0; j < numCols; j++)
    {
        list[i][j] = data;
        data++;
    }

    // 3. Выводим двумерный массив в консоль
    for (unsigned int i = 0; i < numRows; i++)
    {
        for (unsigned int j = 0; j < numCols; j++)
            cout << list[i][j] << " ";
        cout << endl;
    }

    // 4. Освобождаем память
    for (unsigned int i = 0; i < numRows; i++)
    {
        double* p_row = list[i];
        cout << i << ": " << p_row;
        delete[] p_row;
        cout << " -(delete[] p_row)-> " << p_row;
        p_row = nullptr;
        cout << " -(p_row = nullptr)-> " << p_row << endl;
    }
    delete[] list;
    list = nullptr;

    return 0;
}

Ответы (3 шт):

Автор решения: Harry

Вы создали "вещь в себе" — функция Array действительно создает массив, который благополучно теряется. Похоже, вы не разобрались, как работать с функциями. Ваше void (*list)(unsigned int, unsigned int) = Array; — не создание массива, это - указатель на функцию, так что все ваши обращения как к массиву list[] просто нонсенс.

double** Array(unsigned int rows, unsigned int colms)
{
    ...
    return array2d;
}
...
double **list = Array(numRows,numCols);

Можно и через void*, но что это дает? Все равно вы выделяете память для массива double, так что кроме как к типу double** привести результат будет больше не к чему - так зачем эти приведения, которых можно избежать?

→ Ссылка
Автор решения: Den

Вы конечно понаписали, что больно смотреть, и double тоже не поможет при возврате из функции.

Так же вам стоит почитать про передачу параметров в функцию:

  • по значению
  • по ссылке
  • по указателю

Можете почитать тут. Пропустим разбор вашего кода, просто покажу как можно было бы это реализовать:

#include <iostream>

double** create_arr(int rows, int colms){
    double **arr = new double*[rows];
    for (int i(0); i < rows; i++){
        arr[i] = new double[colms];
    }
    return arr;
}

void init(double **arr,int rows, int colms){
    for (int i(0); i < rows; i++){
        for (int j(0); j < colms; j++)
        {
            arr[i][j] = i + j;
        }
    }
}

void printArr(double *arr[],int rows, int colms){
    for (int i(0); i < rows; i++){
        std::cout << std::endl;
        for (int j(0); j < colms; j++){
            std::cout << arr[i][j] << "  ";
        }
    }
}


int main(){
    int row = 4, col = 4;
    double **arr = create_arr(row, col);
    init(arr, row, col);
    printArr(arr, row, col);
}

Как и говорили уже можно использовать void*, но это не имеет смысла, т.к. все равно придется использовать приведение типов.

→ Ссылка
Автор решения: Serge3leo

Понимаю, что легче было бы это сделать через тот же тип double, но мне уже интересно, возможно ли это через void?

Это ложная, кажущаяся лёгкость:

  1. Сложно удалять, забыл удалить - утечка памяти. Полное применение идиомы RAII (получение ресурса есть инициализация...) - очень часто, очень неплохой выбор;
  2. Лишний расход памяти;
  3. Соответственно, для современных ЦП, у которых доступ к памяти самое дорогое, невысокая производительность;
  4. Плюс создание/удаление требуют rows+1 операций выделения/освобождения памяти, что тоже весьма и весьма не шустро. Хотя это можно и исправить, но ценой ещё большего усложнения.

Насчёт желания void, это ваше желание, в принципе, - правильное. Путь C++ - отделить типы от алгоритмов. Только вот не void, но аргумент шаблона.

darr.cpp:

#include <iostream>

// Демонстрационный аналог динамических массивов C (variable length array)
// T x[r][c];

template<class T>
class DemoMatrix {
    size_t rows;  // Не используется, для будущих расширений.
    size_t colms;
    T *matrix;

public:
    DemoMatrix(size_t _rows, size_t _colms) :
        rows(_rows), colms(_colms)
    {
        matrix = new T[rows*colms];
    }

    ~DemoMatrix() {
        delete[] matrix;
    }

    T *operator[](size_t i) {
        return matrix + i*colms;
    }
};

int main() {
    const unsigned numRows = 4;
    const unsigned numCols = 10;
    DemoMatrix<double> list(numRows, numCols);

    for(unsigned i = 0; i < numRows; i++) {
        for(unsigned j = 0; j < numCols; j++) {
            list[i][j] = j + i;
        }
    }

    list[1][3] += 1.2;

    std::cout << list[1][3] << ' ' << list[3][1] << std::endl;
}
→ Ссылка