简体   繁体   English

指针对指针的动态二维数组

[英]Pointer-to-pointer dynamic two-dimensional array

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 DS Malik".我是 C++ 的新手,我目前正在阅读“使用 DS Malik 的 C++ 第 2 版的数据结构”一书。

In the book Malik offers two ways of creating a dynamic two-dimensional array.在书中 Malik 提供了两种创建动态二维数组的方法。 In the first method, you declare a variable to be an array of pointers, where each pointer is of type integer.在第一种方法中,您将变量声明为指针数组,其中每个指针的类型为 integer。 ex.前任。

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.这两种方法都可以用来制作动态二维 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;
}

The first method cannot be used to create dynamic 2D arrays because by doing: 第一种方法不能用于创建动态 2D数组,因为通过执行以下操作:

int *board[4];

you essentially allocated an array of 4 pointers to int on stack . 你基本上在堆栈上分配了一个4个指向int的数组。 Therefore, if you now populate each of these 4 pointers with a dynamic array: 因此,如果现在使用动态数组填充这4个指针中的每一个:

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

what you end-up with is a 2D array with static number of rows (in this case 4) and dynamic number of columns (in this case 10). 你最终得到的是具有静态行数(在这种情况下为4)和动态列数(在这种情况下为10)的2D数组。 So it is not fully dynamic because when you allocate an array on stack you should specify a constant size , ie known at compile-time . 因此它不是完全动态的,因为当您在堆栈上分配数组时,您应该指定一个常量大小 ,即在编译时已知。 Dynamic array is called dynamic because its size is not necessary to be known at compile-time , but can rather be determined by some variable in runtime . 动态数组被称为动态的 ,因为它的大小是没有必要在编译时是已知的,而是可以通过在运行时一些变量来确定。

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-allocate this memory for your array, and when your program is loaded into the memory it would already have this amount of memory for the board array, that's why it is called static , ie because the size is hard-coded and cannot be changed dynamically (in runtime). 你提供一个在编译时已知的常量(在这种情况下是4或x ),这样编译器现在可以为你的数组预先分配这个内存,当你的程序被加载到内存中时,它已经拥有了这个内存量。 board数组,这就是为什么它被称为静态 ,即因为大小是硬编码的并且不能动态地改变 (在运行时)。

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 board array will require, and therefore it does not pre-allocate anything. 编译器不知道内存board阵列需要多少,因此它不预先分配任何东西。 But when you start your program, the size of array would be determined by the value of x variable (in runtime) and the corresponding space for board array 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. 但是当你启动你的程序时,数组的大小将由x变量的值决定(在运行时),并且board数组的相应空间将分配在所谓的堆上 - 所有程序在你的所有程序上运行的内存区域计算机可以预先分配未知 (在编译时)数量的内存供个人使用。

As a result, to truly create dynamic 2D array you have to go with the second method: 因此,要真正创建动态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
}

We've just created an square 2D array with 10 by 10 dimensions. 我们刚刚创建了一个10×10维的方形2D数组。 To traverse it and populate it with actual values, for example 1, we could use nested loops: 要遍历它并使用实际值填充它,例如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;
  }
}

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. 这只是分配一个包含10个元素的数组。 Perhaps you meant something like this: 也许你的意思是这样的:

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 int s. 在这种情况下,我们分配4个int* s然后使每个指向动态分配的10个int的数组。

So now we're comparing that with int* board[4]; 所以现在我们将它与int* board[4];进行比较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* 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. 您可能希望使用std::array<int, std::array<int, 10> 4>或者std::vector<std::vector<int>> ,您可以将其初始化为适当的大小。

In both cases your inner dimension may be dynamically specified (ie 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]; int* x = new int[4]; "better" than int x[4] ? int x[4] “更好”?

The answer is: " no , unless you need to choose that array dimension dynamically." 答案是:“ ,除非你需要动态选择那个数组维度。”

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 each array 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 main and relies solely on std::cin and std::cout . 这是一个非常简单的int main实现,仅依赖于std::cinstd::cout Barebones, but good enough to show how to work with simple multidimensional arrays. Barebones,但足以说明如何使用简单的多维数组。

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

/ / in this method of declaring 2d array using new..first you have created an array of pointers locally not using new so it will be created on stack not on heap then you have created an array using new on every index of p_board, these all arrays are created on heap but due to locally created p_board will make these array of no use becoz when you will use this method in any function and will try to return the p_board pointer from that function..at that time p_board will be vanished from stack because it was created on stack...but 2nd method is preferable to use / //在这个使用new声明二维数组的方法中。首先你在本地创建了一个指针数组,而不是使用new,所以它将在堆栈而不是堆上创建,然后你在p_board的每个索引上使用new创建了一个数组,这些all arrays are created on heap but due to locally created p_board will make these array of no use becoz when you will use this method in any function and will try to return the p_board pointer from that function..at that time p_board will be vanished from堆栈,因为它是在堆栈上创建的......但第二种方法更适合使用/

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

//in this method both array will be created on heap //在这个方法中,两个数组都将在堆上创建

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM