简体   繁体   English

单指针和双指针数组之间的区别

[英]Difference between single-pointer and double-pointer arrays

Code below prints addresses of dynamically allocated array. 下面的代码显示动态分配的数组的地址。 Printed addresses become slightly different, when new line starts. 当新行开始时,打印的地址会稍有不同。 If I use static array, addresses are exactly the same, and array elements are going one after another. 如果我使用静态数组,则地址完全相同,并且数组元素将一个接一个地移动。 What's the reason? 什么原因?

void func(int* a, int** b)
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            cout << &a[i * n + j]<< " " << &b[i][j]<< endl;
        }
        cout << endl;
    }
}

int main()
{
    int** a;
    a = new int*[n];
    for (int i = 0; i < n; i++)
    {
        a[i] = new int[n];
    }
    func(a[0], a);

It's how you created your matrix. 这就是您创建矩阵的方式。 There is no reason to assume that a[0] + 1 * n + j equals a[1] + j . 没有理由假定a[0] + 1 * n + j等于a[1] + j a[0] and a[1] were independently allocated. a[0]a[1]独立分配。

Here is a way to get the entire matrix at once. 这是一次获取整个矩阵的方法。

int** a = new int*[n]; // allocate the row indexes
a[0] = new int[n * n]; // allocate the entire matrix
for (int i = 1; i < n; i++)
{
    a[i] = a[0] + i * n; // assign the row indexes. NOTE: a[0] is already assigned.
}

Using this allocation, a[0] + 1 * n + j equals a[1] + j . 使用此分配, a[0] + 1 * n + j等于a[1] + j


Static arrays allocate the entire matrix allocation implicitly, which is why your code works for them. 静态数组隐式分配整个矩阵分配,这就是为什么您的代码对其有效的原因。

Difference between single-pointer and double-pointer arrays 单指针和双指针数组之间的区别

You can see the difference in the code: 您可以在代码中看到区别:

int** a;         // a is a pointer of type int**
a = new int*[n]; // a points to an array of pointers of type int*

And: 和:

for (int i = 0; i < n; i++)
{
    a[i] = new int[n]; // a[i] points to an array of ints

There you have it. 你有它。

Printed addresses become slightly different, when new line starts. 当新行开始时,打印的地址会稍有不同。 If I use static array, addresses are exactly the same, and array elements are going one after another. 如果我使用静态数组,则地址完全相同,并且数组元素将一个接一个地移动。

Presumably, you're talking about a static array of arrays and compare it to the array of pointers that you have. 大概是在谈论静态数组数组,并将其与您拥有的指针数组进行比较。

Elements of an array are allocated continuously in memory. 数组的元素在内存中连续分配。 In the case of array of static arrays, the elements of the outer array are static arrays and they are stored continuously in memory. 对于静态数组数组,外部数组的元素是静态数组,它们连续存储在内存中。 In the case of array of pointers, the elements of the outer array are the pointers and they are also stored continuously in memory. 对于指针数组,外部数组的元素是指针,它们也连续存储在内存中。 The arrays of int that you allocate dynamically on the other hand are not stored in the outer array. 另一方面,您动态分配的int数组不存储在外部数组中。 Where they're stored is implementation defined and typically not related to the location of the array which holds the pointers. 它们的存储位置是实现定义的,通常与保存指针的数组的位置无关。

Also: 也:

cout << &a[i * n + j]<< " " << &b[i][j]<< endl;

Here you're accessing beyond the borders of the array pointed by the argument a which is pointed by a[0] in main and has a length of n which is less than i * n + j when i is non-zero. 在这里,您正在访问参数a所指向的数组的边界之外,参数a所指向的数组在maina[0]指向,并且长度为n ,当i为非零值时,该长度小于i * n + j The result is technically undefined behaviour and the printed addresses are most definitely not of the elements of arrays that you've allocated. 结果是技术上未定义的行为,并且打印的地址绝对不是您分配的数组元素的绝对值。

Code below prints addresses of dynamically allocated array. 
Printed addresses become slightly different, when new line starts. If
I use static array, addresses are exactly the same, and array elements
are going one after another. What's the reason?

The reason being that The following call will generate a new address every-time it is called and there is no guarantee of that address being contiguous. 原因是以下调用将在每次调用时生成一个新地址,并且不能保证该地址是连续的。 a[i] = new int[n]; a [i] = new int [n];

While, 而,

int a[10][20] 整数a [10] [20]

which is a static array will have contiguous memory allocation. 这是一个静态数组,将具有连续的内存分配。

You're using two conflicting implementations in your modeling of a matrix: in main , you use arrays of arrays, with each row in separate memory; 在矩阵建模中,您使用了两种相互矛盾的实现方式:在main ,您使用的是数组数组,每一行都位于单独的内存中; and in func , you assume a single flat array of rows * columns elements, mapping the two indices to one. func ,假设rows * columns元素的平面数组单一,将两个索引映射为一个。 You have to choose one or the other. 您必须选择一个。

In C++, of course, you'd write a Matrix class, to encapsulate this choice. 当然,在C ++中,您将编写一个Matrix类来封装此选择。 For example, if you wanted the single flat array (usually preferable), you'd write something like: 例如,如果您想要单个平面数组(通常更可取),则可以编写以下内容:

class Matrix
{
    int myRowCount;
    int myColumnCount;
    std::vector<int> myData;
public:
    Matrix( int rows, int columns )
        : myRowCount( rows )
        , myColumnCount( columns )
        , myData( rows * columns )
    {
    }

    int& operator()( int row, int column )
    {
        assert( row >= 0 && row < myRowCount
                && column >= 0 && column < myColumnCount );
        return myData[row * myColumnCount + column];
    }

    int const& operator()( int row, int column ) const
    {
        assert( row >= 0 && row < myRowCount
                && column >= 0 && column < myColumnCount );
        return myData[row * myColumnCount + column];
    }
};

You'll note that I used std::vector rather than doing any dynamic allocation myself. 您会注意到,我使用了std::vector而不是自己进行任何动态分配。 In this case, the difference isn't enormous, but in practice, no experienced C++ programmer would use an array new except in very exceptional cases; 在这种情况下,差异并不大,但是在实践中,除了非常例外的情况外,没有经验的C ++程序员会使用new数组。 one sometimes wonders why it is even in the language. 有时有人想知道为什么它甚至在语言中也是如此。

You'll also note that I have overloaded the () operator for indexing. 您还将注意到,我已经重载了()运算符以进行索引。 You cannot provide two indices for [] , and this is one of the solutions to that problem. 您不能为[]提供两个索引,这是该问题的解决方案之一。 Alternatively, operator[] would take a single index, and return a proxy object which would also take a single index. 另外, operator[]将采用单个索引,并返回一个代理对象,该对象也将采用单个索引。 While this is the solution I prefer, it is more complicated. 虽然这是我更喜欢的解决方案,但它更加复杂。

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

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