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

时间:2014-11-03 10:52:01

标签: c++ pointers

下面的代码打印动态分配的数组的地址。当新行开始时,打印地址会略有不同。如果我使用静态数组,地址完全相同,并且数组元素一个接一个地进行。原因是什么?

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

4 个答案:

答案 0 :(得分:0)

你是如何创建矩阵的。没有理由认为a[0] + 1 * n + j等于a[1] + j。 <{1}}和a[0]是独立分配的。

这是一种立即获取整个矩阵的方法。

a[1]

使用此分配,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. } 等于a[0] + 1 * n + j


静态数组隐式分配整个矩阵分配,这就是你的代码适用于它们的原因。

答案 1 :(得分:0)

  

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

您可以看到代码中的差异:

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

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

你有它。

  

当新行开始时,打印地址会略有不同。如果我使用静态数组,地址完全相同,并且数组元素一个接一个地进行。

据推测,您正在谈论静态数组数组,并将其与您拥有的指针数组进行比较。

数组的元素在内存中连续分配。在静态数组数组的情况下,外部数组的元素是静态数组,它们连续存储在内存中。在指针数组的情况下,外部数组的元素是指针,它们也连续存储在内存中。另一方面,动态分配的int数组不存储在外部数组中。它们存储的位置是实现定义的,通常与保存指针的数组的位置无关。

此外:

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

您可以访问a a[0]所指向的参数main所指向的数组边界以外的地方,其长度为ni * n + j非零时,小于i。结果是技术上未定义的行为,打印的地址绝对不是您已分配的数组元素。

答案 2 :(得分:0)

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?

原因是以下调用每次调用时都会生成一个新地址,并且无法保证该地址是连续的。     a [i] = new int [n];

虽然,

  

int a [10] [20]

这是一个静态数组将具有连续的内存分配。

答案 3 :(得分:0)

您在建模时使用了两个冲突的实现 矩阵:在main中,您使用数组数组,每行都在 分开的记忆;在func中,您假设一个平面数组 rows * columns个元素,将两个索引映射为一个。 你必须选择其中一个。

在C ++中,当然,你要编写一个Matrix类来封装 这个选择。例如,如果您想要单个平面阵列 (通常更可取),你会写一些类似的东西:

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

你会注意到我使用std::vector而不是做任何事情 动态分配自己。在这种情况下,差异不是 但实际上,没有经验丰富的C ++程序员会这么做 除非在非常特殊的情况下使用数组new;一 有时甚至想知道为什么它甚至在语言中。

您还会注意到我已经为()运算符重载了 索引。您无法为[]提供两个索引,这是 解决这个问题的方法之一。或者, operator[]将采用单个索引,并返回代理 也可以采用单个索引的对象。虽然这是 解决方案我更喜欢,它更复杂。