动态大小的多维数组的 C++ 解决方法

Posted

技术标签:

【中文标题】动态大小的多维数组的 C++ 解决方法【英文标题】:C++ Workaround for multidimensional arrays of dynamic size 【发布时间】:2018-05-31 14:24:00 【问题描述】:

我正在寻找一种简单的解决方法,将动态大小的二维数组作为 5 年级学生可以轻松使用的参数。我目前正在为微控制器研讨会编写一个库,并希望它尽可能易于使用,而无需解释指针、模板等,因为没有时间这样做。

我有以下类,称为 LEDBitmap,由于另一个库中的限制,它的最大宽度为 8,并表示 LED 矩阵的 1 和 0 位图:

头文件:

#ifndef LEDBITMAP_H
#define LEDBITMAP_H

#include <Arduino.h>

class LEDBitmap


  public:
    LEDBitmap(uint8_t width, uint8_t height, uint8_t data[][8]);
    LEDBitmap(uint8_t width, uint8_t height);
    virtual ~LEDBitmap() 
      delete [] _data;
    ;

  public: //methods
    uint8_t* getBitmap();
    uint8_t getPixelValue(uint8_t x, uint8_t y) 
      return _data[y][x];
    ;

    void setPixelValue(uint8_t x, uint8_t y, uint8_t value) 
      _data[y][x] = value;
    ;

    uint8_t getHeight() 
      return _height;
    ;

    uint8_t getWidth() 
      return _width;
    ;

    uint8_t getSize() 
      return _width * _height;
    ;

    void clear();

  private: //members
    uint8_t _width;
    uint8_t _height;
    uint8_t _data[][8];


;

#endif

还有cpp文件:

#include "LEDBitmap.h"

LEDBitmap::LEDBitmap(uint8_t width, uint8_t height) 
  _width = width;
  _height = height;
  _data = new uint8_t[width][height];
  clear();


LEDBitmap::LEDBitmap(uint8_t width, uint8_t height, uint8_t data[][8]) 
  _width = width;
  _height = height;
  _data = data;


uint8_t* LEDBitmap::getBitmap() 
  uint8_t result[_height];
  for (uint8_t h = 0; h < _height; h++) 
    uint8_t binary = 0;
    for (uint8_t w = 0; w < _width; w++) 
      binary |= _data[h][w] << (_width - w+1);
    
    result[h] = binary;
  
  return result;


void LEDBitmap::clear() 
  for (uint8_t h = 0; h < _height; h++) 
    for (uint8_t w = 0; w < _width; w++) 
      _data[h][w] = 0;
    
  

我的问题是第一个构造函数,其中参数uint8_t data[][8] 应该是任意高度和最大宽度为 8 但可能更小的数组。

我曾尝试使用模板,但意识到这会导致代码的其他部分出现更大的问题。如果我要使用模板,那么它们只能在构造函数中使用,而不必执行 LEDBitmap&lt;5, 5&gt; image = ... 之类的操作,而只需使用 LEDBitmap image = LEDBitmap&lt;5, 5&gt;(...)

无法使用向量,因为它们不是 Arduino IDE 的一部分,它是用 C 编写的。我的库是用 C++ 编写的,因为我正在使用其他一些 C++ 库和最初想使用不同的平台,但由于一些问题,我最近不得不切换到 Arduino。

我目前遇到的错误是:no known conversion for argument 3 from 'uint8_t [3][3] aka unsigned char [3][3]' to 'uint8_t (*)[8] aka unsigned char (*)[8]'

提前感谢您的提示和帮助。

【问题讨论】:

std::vector&lt;std::vector&lt;char&gt;&gt; 应该是此类问题的默认解决方案。如果LEDBitmap被正确封装,则不需要更改任何其他代码。 “为了简单起见,我也想尽量远离向量……” 这就是问题所在。 std::vector 应该是第一选择的容器。你应该使用std::vector&lt;std::vector&lt;&gt;&gt;。或者教C而不是C++ 是的,应该是,但如上所述,为了简单起见,我想尽量远离那些,因为五年级学生使用数组更容易 C 数组有各种各样的问题,衰减到指针;动态大小需要使用new;不知道自己的大小。 看起来这适用于 Arduino,而且 afaik,它不支持 vector(或 std lib 的其余部分)oob。 【参考方案1】:

C++ 不喜欢可变长度数组(即使在某些实现中支持,也从未在标准中定义)也不喜欢原始 2D 数组。如果您不需要真正的[] 运营商支持,我的建议是使用访问器函数:

class Array2D 
    size_t width, height;
    uint8_t *data;

public:
    Array2D(size_t width, size_t height): width(width), height(height() 
        data = new uint8_t[width * height];
    
    ~Arrayt2D() 
        delete[] data;
    
    // copy/move ctor-assignment operator omitted for brievety but REQUIRED (law of three/five)

    uint8_t getVal(size_t i, size_t j) const 
        return data[i + j * width];
    
    uint8_t setVal(uint8_t val, size_t i, size_t j) 
        data[i + j * width] = val;
    
    /* alternatively to use arr.val(i, j) = value :
    uint8_t& val(size_t i, size_t j) 
        return data[i + j * width];
    
    */
    // other accessors (height, width) omitted but probably useful...
;

相当 C-ish,但由于您不能使用向量并且更喜欢避免使用模板,因此它可能是一个基本骨架...

【讨论】:

以上是关于动态大小的多维数组的 C++ 解决方法的主要内容,如果未能解决你的问题,请参考以下文章

表示为一维的多维数组(模板化为 n 维)

在 C++ 中将 memset 与多维数组一起使用

如何在 C++ 中正确使用动态分配的多维数组 [重复]

如何将多维动态数组传递给C++中的函数

内存堆问题 C++,动态分配多维数组

多维数组