Подтвердить что ты не робот

Динамический двумерный массив с указателем на указатель

Первый таймер на этом веб-сайте, поэтому здесь идет.

Я новичок на С++, и сейчас я работаю над книгой "Структуры данных, использующие С++ 2nd ed, D.S. Malik".

В книге Малик предлагает два способа создания динамического двумерного массива. В первом методе вы объявляете переменную как массив указателей, где каждый указатель имеет тип integer. напр.

int *board[4];

.. и затем использовать for-loop для создания "столбцов" при использовании массива указателей как "строк".

Второй метод, вы используете указатель на указатель.

int **board;
board = new int* [10]; 

и др.

Мой вопрос таков: какой метод лучше? Метод ** мне легче визуализировать, но первый метод можно использовать почти так же. Оба способа можно использовать для создания динамических 2-мерных массивов.

Изменить: не было достаточно ясно, как указано выше. Вот какой код я пробовал:

int row, col;

cout << "Enter row size:";
cin >> row;
cout << "\ncol:";
cin >> col;

int *p_board[row];
for (int i=0; i < row; i++)
    p_board[i] = new int[col];

for (int i=0; i < row; i++)
{
    for (int j=0; j < col; j++)
    {
        p_board[i][j] = j;
        cout << p_board[i][j] << " ";
    }
    cout << endl;
}
cout << endl << endl;

int **p_p_board;
p_p_board = new int* [row];
for (int i=0; i < row; i++)
    p_p_board[i] = new int[col];

for (int i=0; i < row; i++)
{
    for (int j=0; j < col; j++)
    {
        p_p_board[i][j] = j;
        cout << p_p_board[i][j] << " ";
    }
    cout << endl;
}
4b9b3361

Ответ 1

Первый метод нельзя использовать для создания динамических 2D-массивов, потому что:

int *board[4];

вы по существу выделили массив из 4 указателей на int на стек. Поэтому, если вы теперь заполняете каждый из этих 4 указателей динамическим массивом:

for (int i = 0; i < 4; ++i) {
  board[i] = new int[10];
}

то, что вы заканчиваете, представляет собой 2D-массив с статическим числом строк (в данном случае 4) и динамическим числом столбцов (в данном случае 10). Таким образом, динамика не полностью, так как при распределении массива в стеке вы должны указывать постоянный размер, т.е. Известный в время. Динамический массив называется динамическим, потому что его размер не обязательно должен быть известен в время компиляции, но скорее может быть определен некоторой переменной в во время выполнения.

Еще раз, когда вы выполните:

int *board[4];

или

const int x = 4; // <--- `const` qualifier is absolutely needed in this case!
int *board[x];

вы предоставляете константу, известную в время компиляции (в данном случае 4 или x), чтобы компилятор теперь мог предварительно выделить эту память для вашего массива, и когда ваша программа будет загружена в память, у нее уже будет этот объем памяти для массива board, поэтому он называется static, т.е. потому что размер жестко закодирован и не могут динамически меняться (во время выполнения).

С другой стороны, когда вы делаете:

int **board;
board = new int*[10];

или

int x = 10; // <--- Notice that it does not have to be `const` anymore!
int **board;
board = new int*[x];

компилятор не знает, сколько потребуется массиву памяти board, и поэтому он не заранее выделяет все. Но когда вы запускаете свою программу, размер массива будет определяться значением переменной x (во время выполнения), а соответствующее пространство для массива board будет выделено на так называемую кучу - область памяти, в которой все программы, запущенные на вашем компьютере, могут выделять неизвестно заранее (во время компиляции) суммирует память для личного использования.

В результате, чтобы действительно создать динамический 2D-массив, вам нужно пойти со вторым методом:

int **board;
board = new int*[10]; // dynamic array (size 10) of pointers to int

for (int i = 0; i < 10; ++i) {
  board[i] = new int[10];
  // each i-th pointer is now pointing to dynamic array (size 10) of actual int values
}

Мы только что создали квадратный 2D-массив размером 10 на 10. Чтобы пройти его и заполнить его фактическими значениями, например 1, мы могли бы использовать вложенные циклы:

for (int i = 0; i < 10; ++i) {   // for each row
  for (int j = 0; j < 10; ++j) { // for each column
    board[i][j] = 1;
  }
}

Ответ 2

То, что вы описываете для второго метода, дает только 1D-массив:

int *board = new int[10];

Это просто выделяет массив с 10 элементами. Возможно, вы имели в виду что-то вроде этого:

int **board = new int*[4];
for (int i = 0; i < 4; i++) {
  board[i] = new int[10];
}

В этом случае мы выделяем 4 int*, а затем каждый из них укажем на динамически выделенный массив из 10 int s.

Итак, теперь мы сравниваем это с int* board[4];. Основное различие заключается в том, что при использовании такого массива количество "строк" ​​должно быть известно во время компиляции. Это потому, что массивы должны иметь фиксированные размеры времени компиляции. У вас может также возникнуть проблема, если вы хотите, возможно, вернуть этот массив из int* s, поскольку массив будет уничтожен в конце его области.

Метод, в котором динамически распределяются как строки, так и столбцы, требует более сложных мер, чтобы избежать утечек памяти. Вы должны освободить память так:

for (int i = 0; i < 4; i++) {
  delete[] board[i];
}
delete[] board;

Я должен рекомендовать вместо этого использовать стандартный контейнер. Вы можете использовать std::array<int, std::array<int, 10> 4> или, возможно, std::vector<std::vector<int>>, который вы инициализируете соответствующим размером.

Ответ 3

В обоих случаях ваше внутреннее измерение может быть динамически задано (т.е. взято из переменной), но разница во внешнем измерении.

Этот вопрос в основном эквивалентен следующему:

Является int* x = new int[4]; "лучше", чем int x[4]?

Ответ: "нет, если вам не нужно выбирать этот размер массива динамически".

Ответ 4

Этот код хорошо работает с очень небольшим количеством требований к внешним библиотекам и показывает базовое использование int **array.

Этот ответ показывает, что массив each имеет динамический размер, а также как назначить линейный массив динамически размера в массив ветвей динамического размера.

Эта программа принимает аргументы из STDIN в следующем формате:

2 2   
3 1 5 4
5 1 2 8 9 3
0 1
1 3

Код для программы ниже...

#include <iostream>

int main()
{
    int **array_of_arrays;

    int num_arrays, num_queries;
    num_arrays = num_queries = 0;
    std::cin >> num_arrays >> num_queries;
    //std::cout << num_arrays << " " << num_queries;

    //Process the Arrays
    array_of_arrays = new int*[num_arrays];
    int size_current_array = 0;

    for (int i = 0; i < num_arrays; i++)
    {
        std::cin >> size_current_array;
        int *tmp_array = new int[size_current_array];
        for (int j = 0; j < size_current_array; j++)
        {
            int tmp = 0;
            std::cin >> tmp;
            tmp_array[j] = tmp;
        }
        array_of_arrays[i] = tmp_array;
    }


    //Process the Queries
    int x, y;
    x = y = 0;
    for (int q = 0; q < num_queries; q++)
    {
        std::cin >> x >> y;
        //std::cout << "Current x & y: " << x << ", " << y << "\n";
        std::cout << array_of_arrays[x][y] << "\n";
    }

    return 0;
}

Это очень простая реализация int main и зависит только от std::cin и std::cout. Barebones, но достаточно хорошо, чтобы показать, как работать с простыми многомерными массивами.

Ответ 5

это можно сделать следующим образом

  1. Я использовал перегрузку оператора
  2. Перегруженное назначение
  3. Конструктор перегруженного копирования

    /*
     * Soumil Nitin SHah
     * Github: https://github.com/soumilshah1995
     */
    
    #include <iostream>
    using namespace std;
            class Matrix{
    
    public:
        /*
         * Declare the Row and Column
         *
         */
        int r_size;
        int c_size;
        int **arr;
    
    public:
        /*
         * Constructor and Destructor
         */
    
        Matrix(int r_size, int c_size):r_size{r_size},c_size{c_size}
        {
            arr = new int*[r_size];
            // This Creates a 2-D Pointers
            for (int i=0 ;i < r_size; i++)
            {
                arr[i] = new int[c_size];
            }
    
            // Initialize all the Vector to 0 initially
            for (int row=0; row<r_size; row ++)
            {
                for (int column=0; column < c_size; column ++)
                {
                    arr[row][column] = 0;
                }
            }
            std::cout << "Constructor -- creating Array Size ::" << r_size << " " << c_size << endl;
        }
    
        ~Matrix()
        {
            std::cout << "Destructpr  -- Deleting  Array Size ::" << r_size <<" " << c_size << endl;
    
        }
    
        Matrix(const Matrix &source):Matrix(source.r_size, source.c_size)
    
        {
            for (int row=0; row<source.r_size; row ++)
            {
                for (int column=0; column < source.c_size; column ++)
                {
                    arr[row][column] = source.arr[row][column];
                }
            }
    
            cout << "Copy Constructor " << endl;
        }
    
    
    public:
        /*
         * Operator Overloading
         */
    
        friend std::ostream &operator<<(std::ostream &os, Matrix & rhs)
        {
            int rowCounter = 0;
            int columnCOUNTER = 0;
            int globalCounter = 0;
    
            for (int row =0; row < rhs.r_size; row ++)
            {
                for (int column=0; column < rhs.c_size ; column++)
                {
                    globalCounter = globalCounter + 1;
                }
                rowCounter = rowCounter + 1;
            }
    
    
            os << "Total There are " << globalCounter << " Elements" << endl;
            os << "Array Elements are as follow -------" << endl;
            os << "\n";
    
            for (int row =0; row < rhs.r_size; row ++)
            {
                for (int column=0; column < rhs.c_size ; column++)
                {
                    os << rhs.arr[row][column] << " ";
                }
            os <<"\n";
            }
            return os;
        }
    
        void operator()(int row, int column , int Data)
        {
            arr[row][column] = Data;
        }
    
        int &operator()(int row, int column)
        {
            return arr[row][column];
        }
    
        Matrix &operator=(Matrix &rhs)
                {
                    cout << "Assingment Operator called " << endl;cout <<"\n";
                    if(this == &rhs)
                    {
                        return *this;
                    } else
                        {
                        delete [] arr;
    
                            arr = new int*[r_size];
                            // This Creates a 2-D Pointers
                            for (int i=0 ;i < r_size; i++)
                            {
                                arr[i] = new int[c_size];
                            }
    
                            // Initialize all the Vector to 0 initially
                            for (int row=0; row<r_size; row ++)
                            {
                                for (int column=0; column < c_size; column ++)
                                {
                                    arr[row][column] = rhs.arr[row][column];
                                }
                            }
    
                            return *this;
                        }
    
                }
    
    };
    
                int main()
    {
    
        Matrix m1(3,3);         // Initialize Matrix 3x3
    
        cout << m1;cout << "\n";
    
        m1(0,0,1);
        m1(0,1,2);
        m1(0,2,3);
    
        m1(1,0,4);
        m1(1,1,5);
        m1(1,2,6);
    
        m1(2,0,7);
        m1(2,1,8);
        m1(2,2,9);
    
        cout << m1;cout <<"\n";             // print Matrix
        cout << "Element at Position (1,2) : " << m1(1,2) << endl;
    
        Matrix m2(3,3);
        m2 = m1;
        cout << m2;cout <<"\n";
    
        print(m2);
    
        return 0;
    }