C++ 指针对指针动态二维数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16001803/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:00:01  来源:igfitidea点击:

Pointer-to-pointer dynamic two-dimensional array

c++arrayspointersmemory-managementdynamic-arrays

提问by user2280041

First timer on this website, so here goes..

这个网站上的第一个计时器,所以在这里..

I'm a newbie to C++ and I'm currently working through the book "Data structures using C++ 2nd ed, of D.S. Malik".

我是 C++ 的新手,目前正在阅读“DS Malik 的《使用 C++ 第二版的数据结构》”一书。

In the book Malik offers two ways of creating a dynamic two-dimensional array. In the first method, you declare a variable to be an array of pointers, where each pointer is of type integer. ex.

在这本书中,Malik 提供了两种创建动态二维数组的方法。在第一种方法中,您将一个变量声明为一个指针数组,其中每个指针都是整数类型。前任。

int *board[4];

..and then use a for-loop to create the 'columns' while using the array of pointers as 'rows'.

..然后使用for循环创建“列”,同时使用指针数组作为“行”。

The second method, you use a pointer to a pointer.

第二种方法,您使用指向指针的指针。

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

etc.

等等。

My question is this: which is the better method? The ** method is easier for me to visualize, but the first method can be used in much the same way. Both ways can be used to make dynamic 2-d arrays.

我的问题是:哪种方法更好?** 方法对我来说更容易想象,但第一种方法可以以大致相同的方式使用。这两种方式都可以用来制作动态二维数组。

Edit: Wasn't clear enough with the above post. Here's some code I tried:

编辑:上面的帖子不够清楚。这是我尝试过的一些代码:

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

回答by Alexander Shukaev

The first method cannot be used to create dynamic2D arrays because by doing:

第一种方法不能用于创建动态二维数组,因为这样做:

int *board[4];

you essentially allocated an array of 4 pointers to inton stack. Therefore, if you now populate each of these 4 pointers with a dynamic array:

您基本上分配了一个指向inton stack的 4 个指针的数组。因此,如果您现在使用动态数组填充这 4 个指针中的每一个:

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

what you end-up with is a 2D array with staticnumber of rows (in this case 4) and dynamicnumber of columns (in this case 10). So it is not fullydynamic because when you allocate an array on stack you shouldspecify a constant size, i.e. known at compile-time. Dynamicarray is called dynamicbecause its size is not necessary to be known at compile-time, but can rather be determined by some variable in runtime.

您最终得到的是一个具有静态行数(在本例中为 4)和动态列数(在本例中为 10)的二维数组。所以它不是完全动态的,因为当你在堆栈上分配一个数组时,你应该指定一个常量大小,即在编译时已知。动态数组称为动态因为它的大小是没有必要在被称为编译时,而是可以通过在一些变量来确定运行时间

Once again, when you do:

再一次,当你这样做时:

int *board[4];

or:

或者:

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

you supply a constant known at compile-time(in this case 4 or x) so that compiler can now pre-allocatethis memory for your array, and when your program is loaded into the memory it would already have this amount of memory for the boardarray, that's why it is called static, i.e. because the size is hard-codedand cannot be changed dynamically(in runtime).

您提供一个在编译时已知的常量(在本例中为 4 或x),以便编译器现在可以为您的数组预先分配此内存,并且当您的程序加载到内存中时,它已经为board数组提供了这个内存量,这就是为什么它被称为static,即因为大小是硬编码的并且不能动态更改(在运行时)。

On the other hand, when you do:

另一方面,当你这样做时:

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

or:

或者:

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

the compiler does not know how much memory boardarray will require, and therefore it does not pre-allocateanything. But when you start your program, the size of array would be determined by the value of xvariable (in runtime) and the corresponding space for boardarray would be allocated on so-called heap- the area of memory where all programs running on your computer can allocate unknown beforehand(at compile-time) amounts memory for personal usage.

编译器不知道需要多少内存board数组,因此它不会预先分配任何东西。但是当你启动你的程序时,数组的大小将由x变量的值(在运行时)决定,数组的相应空间board将分配在所谓的堆上- 计算机上运行的所有程序都可以使用的内存区域预先分配未知数(在编译时)供个人使用的内存量。

As a result, to truly create dynamic 2D array you have to go with the second method:

因此,要真正创建动态二维数组,您必须使用第二种方法:

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
}

We've just created an square 2D array with 10 by 10 dimensions. To traverse it and populate it with actual values, for example 1, we could use nested loops:

我们刚刚创建了一个 10 x 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;
  }
}

回答by Joseph Mansfield

What you describe for the second method only gives you a 1D array:

您为第二种方法描述的内容只为您提供了一个一维数组:

int *board = new int[10];

This just allocates an array with 10 elements. Perhaps you meant something like this:

这只是分配了一个包含 10 个元素的数组。也许你的意思是这样的:

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

In this case, we allocate 4 int*s and then make each of those point to a dynamically allocated array of 10 ints.

在这种情况下,我们分配 4int*秒,然后使每个指向动态分配的 10int秒数组。

So now we're comparing that with int* board[4];. The major difference is that when you use an array like this, the number of "rows" must be known at compile-time. That's because arrays must have compile-time fixed sizes. You may also have a problem if you want to perhaps return this array of int*s, as the array will be destroyed at the end of its scope.

所以现在我们将它与int* board[4];. 主要区别在于,当您使用这样的数组时,必须在编译时知道“行”的数量。那是因为数组必须具有编译时固定大小。如果您想返回这个int*s数组,您也可能会遇到问题,因为该数组将在其作用域结束时被销毁。

The method where both the rows and columns are dynamically allocated does require more complicated measures to avoid memory leaks. You must deallocate the memory like so:

动态分配行和列的方法确实需要更复杂的措施来避免内存泄漏。您必须像这样释放内存:

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

I must recommend using a standard container instead. You might like to use a std::array<int, std::array<int, 10> 4>or perhaps a std::vector<std::vector<int>>which you initialise to the appropriate size.

我必须建议改用标准容器。您可能想使用 astd::array<int, std::array<int, 10> 4>或 astd::vector<std::vector<int>>初始化为适当的大小。

回答by Lightness Races in Orbit

In both cases your inner dimension may be dynamically specified (i.e. taken from a variable), but the difference is in the outer dimension.

在这两种情况下,您的内部维度可能是动态指定的(即从变量中获取),但区别在于外部维度。

This question is basically equivalent to the following:

这个问题基本上等同于以下问题:

Is int* x = new int[4];"better" than int x[4]?

int* x = new int[4];“更好”比int x[4]

The answer is: "no, unless you need to choose that array dimension dynamically."

答案是:“,除非您需要动态选择该数组维度。”

回答by Andrew

This code works well with very few requirements on external libraries and shows a basic use of int **array.

此代码运行良好,对外部库的要求很少,并显示了int **array.

This answer shows that eacharray is dynamically sized, as well as how to assign a dynamically sized leaf array into the dynamically sized branch array.

这个答案表明每个数组都是动态大小的,以及如何将动态大小的叶子数组分配到动态大小的分支数组中。

This program takes arguments from STDIN in the following format:

该程序采用以下格式从 STDIN 获取参数:

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

Code for program below...

下面的程序代码...

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

It's a very simple implementation of int mainand relies solely on std::cinand std::cout. Barebones, but good enough to show how to work with simple multidimensional arrays.

这是一个非常简单的实现int main并且完全依赖于std::cinand std::cout。准系统,但足以展示如何使用简单的多维数组。

回答by Soumil Nitin Shah

this can be done this way

这可以通过这种方式完成

  1. I have used Operator Overloading
  2. Overloaded Assignment
  3. Overloaded Copy Constructor

    /*
     * 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;
    }
    
  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;
    }