【问题标题】:stuck on copying memory managed by a double pointer to a two-dimensional array坚持将双指针管理的内存复制到二维数组
【发布时间】:2019-10-12 09:59:39
【问题描述】:

代码如下:

#include <iostream>
using std::cout;

int main(int argc, char ** argv)
{
    int** p;
    int a[2][3]={{-1,-1,-1},
                 {-1,-1,-1}};
    int k=1;
    p = new int *[2];
    for(int i=0;i<2;i++) {
        p[i] = new int[3];
        for(int j=0;j<3;j++) {
            p[i][j] = k++;
        }
    }

    memcpy(a,p,2 * 3 * sizeof(int));
    for(int i=0;i<2;i++){
        for(int j=0;j<3;j++)
            cout<<a[i][j]<<" ";
        cout<<endl;
    }

    delete [] p;
    return 0;
}

运行后得到了意想不到的结果:

26573888 0 26573920
0   0   0

我认为它复制了地址而不是值,所以我将 memcpy(a,p,2 * 3 * sizeof(int)); 行更改为

memcpy(a,p[0],2 * 3 * sizeof(int));

终端打印出来:

1 2 3
0 0 0

如何理解上述结果?谁能帮帮我?

猜猜
p[0][2]和p[1][0]的地址不连续?

【问题讨论】:

  • 您想要实现的实际目标是什么?您想将静态数组复制到动态数组吗?或者你只是想了解内存布局?你的代码的目的是什么?
  • 撤回近距离投票:可能的重复只关注多维数组,而没有充分说明指针数组的差异(这些在内存中是如何布局的?)。

标签: c++ multidimensional-array memory-management


【解决方案1】:

p[0]的类型是什么?

int*

a[0]的类型是什么?

int[3]

a[0] 衰减 指向适当上下文中的指针(例如,当作为参数传递给函数时),但它本身不是一个指针,与 p[0] 完全相反,后者正好来自开始。如果你 e. 你会注意到差异。 G。比较两者的大小(sizeof(a[0]) 给出三个整数的大小,sizeof(p[0]) 给出一个指针的大小)。

数组成员总是只是一个接一个地连续放置,所以对于a,有两个数组一个接一个地放置:

a: { { -1, -1, -1 }, {-1, -1, -1 } }

对于p其实完全一样,每个成员一个接一个地跟随;只是,这一次,成员是真正的指针(即内存中的某个地址)。 还有其他数组,但这些(必然)放置在别处:

p: { <pointer>, <pointer> }
         |          |
         V          |
       { 1, 2, 3}   |
                    V
                  { 4, 5, 6}

总之,你的猜测是正确的。

【讨论】:

    【解决方案2】:

    您必须每行执行一次memcpy 才能获得预期结果:

    memcpy(a[0], p[0], 3 * sizeof(int));
    memcpy(a[1], p[1], 3 * sizeof(int));
    

    原因是行不连续。

    直播godbolt

    【讨论】:

      【解决方案3】:

      你在混合东西......

      This other question(尤其是接受的答案)很好地解释了它。 你有一个静态二维数组和一个int**。

      这两个看起来一样,但不是。编译器知道哪个是哪个,所以一个连续布局,另一个不连续布局。

      您甚至可以在代码中看到这一点。 一旦你写了

      int a[2][3]={{-1,-1,-1},
                   {-1,-1,-1}};
      

      对象是一块内存,用a表示

      然后你写

      p = new int *[2];
      for(int i=0;i<2;i++) {
          p[i] = new int[3];
          for(int j=0;j<3;j++) {
              p[i][j] = k++;
          }
      }
      

      你有一个对象p。然后使用 p[i] = new int[3] 行继续制作 2 个单独的 int[3] 对象。 这些谎言谁知道在哪里。并将它们的地址分配给指针p[i]。

      TL;DR: int[2][3] 类型与 int** 有着根本的不同,而且它们之间的互操作性并不简单。

      【讨论】:

      • 我明白你的意思,但我想强调一点,很容易通过new int[3] 行识别出这两个对象不同。我看到我的大部分答案都是对另一个答案的回顾,我会尝试重写......
      • 再次阅读其他问题和答案,我认为它不是完全重复,另一个问题确实很好地解释了多维数组的内存布局,但缺乏强调与数组的区别指针,所以让我们忘记我之前的评论(已删除)......
      猜你喜欢
      • 2011-11-27
      • 2013-12-23
      • 1970-01-01
      • 1970-01-01
      • 2018-04-18
      • 1970-01-01
      • 2021-10-20
      相关资源
      最近更新 更多