RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 848947
Accepted
Alex Nem
Alex Nem
Asked:2020-07-02 00:28:42 +0000 UTC2020-07-02 00:28:42 +0000 UTC 2020-07-02 00:28:42 +0000 UTC

C++ 中的动态和静态 n 维数组

  • 772

看来我不太明白什么是 C++ 中的二维(n 维)数组,它们是用于 RAM 的,以及在堆栈上声明的二维数组是这样的:

RGBQUAD frameBuffer[300][300];

不同于动态声明的二维数组:

RGBQUAD ** frame = new RGBQUAD*[height];

for (uint32_t i = 0; i < height; i++)
{
    frame[i] = new RGBQUAD[width];
    std::fill_n(frame[i], width, clearColor);
}

现在稍微介绍一下任务本身

我决定尝试编写类似software-renderera的东西,我决定从最基本的点开始(即在屏幕上显示它)。在 WinAPI 中,当然有绘制和设置单个像素颜色的工具,但是在对这个主题进行了一些修改后,我意识到正确的做法是将帧准备为位图图像,然后显示此图像在窗户上。也就是说,按照计划,我将形成一个位图,我会以一定的频率将其显示在窗口上,从而得到类似动画的东西。就其本身而言,我所拥有的图片的显示是这样进行的:

// Cоздать временный bitmap (4 байта на пиксель), последний параметр типа void*
// Это может быть как одномерный так и двумерный массив структур RGBQUAD
HBITMAP hBitMap = CreateBitmap(width, height, 1, 8 * 4, pixels);

// Получить device context окна
HDC hdc = GetDC(hWnd);

// Временный DC для переноса bit-map'а
HDC srcHdc = CreateCompatibleDC(hdc);

// Связать bit-map с временным DC
SelectObject(srcHdc, hBitMap);

// Копировать содержимое временного DC в DC окна
BitBlt(
    hdc,    // HDC назначения
    0,      // Начало вставки по оси X
    0,      // Начало вставки по оси Y
    width,  // Ширина
    height, // Высота
    srcHdc, // Исходный HDC (из которого будут копироваться данные)
    0,      // Начало считывания по оси X
    0,      // Начало считывания по оси Y
    SRCCOPY // Копировать
);

// Уничтожить bit-map
DeleteObject(hBitMap);
// Уничтожить временный DC
DeleteDC(srcHdc);
// Уничтожить DC
DeleteDC(hdc);

一切正常,令人惊讶的是,它同时使用一维和二维结构数组作为参数pixels(在函数中CreateBitmap)。好像C ++中没有动态声明的二维数组被视为一维..然后我尝试在堆上动态分配相同的帧缓冲区(二维数组),即事实上,创建一个指向数组的指针数组,这正是我所做的)。最后,一切都停止了工作,现在该功能CreateBitmap不明白这一点。然后我尝试动态分配一个一维数组,如下所示:

RGBQUAD * frame = new RGBQUAD[width * height];
std::fill_n(frame, width * height, clearColor);

一切都立即开始起作用。

问:怎么了?我错过了什么?在 C++ 中动态声明的二维数组是否与以通常方式声明的二维数组不同?有什么区别?提前致谢。

c++
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    HolyBlackCat
    2020-07-02T01:27:23Z2020-07-02T01:27:23Z

    对于普通数组,比如int a[3]and int b[3][3],只有元素本身在内存中连续存储,仅此而已。

    int a[3]
    
    .------.------.------.------.------.
    | a[0] | a[1] | a[2] | a[3] | a[4] |
    '------'------'------'------'------'
    
    int b[3][2]
    
    .---------.---------.---------.---------.---------.---------.
    | b[0][0] | b[0][1] | b[1][0] | b[1][1] | b[2][0] | b[2][1] | 
    '---------'---------'---------'---------'---------'---------'
    

    这就是使用new. 指向第一个元素的指针单独存储。

    int *c = new int[5]
    
    .-----.
    |  c  |
    '--.--'
       |
       |
       V
    .-----.-----.-----.-----.-----.
    | [0] | [1] | [2] | [3] | [4] |
    '-----'-----'-----'-----'-----'
    

    对于多维数组,您使用了指向数组的指针数组,也就是“撕裂”数组。

    int **d = new int*[3];
    for (int i = 0; i < 3; i++)
        d[i] = new int[4];
    
    .-----.
    |  d  |
    '--.--'
       |
       |
       V
    .-----.-----.-----.
    | [0] | [1] | [2] |
    '--.--'--.--'--.--'
       |     |     |        .--------.--------.--------.--------.
       |     |     '------> | [2][0] | [2][1] | [2][2] | [2][3] |
       |     |              '--------'--------'--------'--------'
       |     |        .--------.--------.--------.--------.
       |     '------> | [1][0] | [1][1] | [1][2] | [1][3] |
       |              '--------'--------'--------'--------'
       |        .--------.--------.--------.--------.
       '------> | [0][0] | [0][1] | [0][2] | [0][3] |
                '--------'--------'--------'--------'
    

    在这种情况下,行不必连续位于内存中,这与以通常方式创建的数组不同,例如int f[3][4].

    使行连续进入内存的最方便(在我看来)方法,您已经发现:使用一维数组:int *g = new int[w * h];。

    如果您想使用一种方便的语法来访问元素:g[y][x]而不是g[y * w + x],那么最好使用重载的运算符创建您自己的二维数组类[]。


    顺便说一句,我强烈建议您使用代替newand 。deletestd::vector

    使用 new/delete,很容易忘记释放内存和泄漏。你被折磨着以后再搜索。

    如果代码中的某些内容引发异常,则特别容易忘记。

    Astd::vector为您监视内存的释放。

    • 8
  2. user245150
    2020-07-02T01:01:22Z2020-07-02T01:01:22Z

    不同的是静态二维数组和一维数组没有区别,所以在图上会这样定位(二维5x5静态数组的例子)ロ表示一个单元格

    ロロロロロ ロロロロロ ロロロロロ
    

    并且在动态二维数组中,所有的第一个元素都是指针,并且所有元素都分别位于RAM中(二维动态数组5x5的例子)上图&表示一个链接

    &1 ---> ロロロロロ
    &2 ---> ロロロロロ
    &3 ---> ロロロロロ
    &4 ---> ロロロロロ
    &5 ---> ロロロロロ
    

    因此,它们随机分散在 RAM 中,与静态二维数组不同

    如果你想要一个连续的二维数组,有一个选项

    int arr = new int[w*h];
    
    • 4

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5