构造函数中的 C++ 二维数据数组 - 何时初始化和删除?
C++ 2D data array in constructor - When to initialize and delete?
这个问题可能有点愚蠢,但我对 C++ 还是个新手,我已经有一段时间没用它做了什么了。
我有一个名为 LEDBitmap
的 class,它应该保存位图的宽度、高度和数据,只有 1 和 0。
在头文件中我有以下结构:
struct MapData
{
uint8_t width;
uint8_t height;
uint8_t[][] data;
};
以及下面的构造函数、析构函数和成员变量:
class LEDBitmap
{
public:
LEDBitmap(uint8_t width, uint8_t, height, uint8_t data[][]);
LEDBitmap(uint8_t width, uint8_t, height);
virtual ~LEDBitmap() { };
[...]
private: //members
MapData _map;
};
我现在想编写构造函数,可能还有析构函数,到目前为止,第一个构造函数如下:
//initialize an empty bitmap with only zeros in it
LEDBitmap::LEDBitmap(uint8_t width, uint8_t, height) {
_map.width = width;
_map.height = height;
_map.data = new uint8_t[width][height];
}
这个实现可行吗? (可能不会)
我应该费心去实际实现析构函数吗?
编辑:
根据@gsamaras 的建议调整了我的代码。
_map
以前是*_ptr
。
编辑: 一位朋友建议改用 calloc()
。因此我现在有:
LEDBitmap::LEDBitmap(uint8_t width, uint8_t height) {
_map.width = width;
_map.height = height;
_map.data = calloc(width*height*(sizeof(uint8_t));
}
和
class LEDBitmap
{
public:
LEDBitmap(uint8_t width, uint8_t, height, uint8_t data[][]);
LEDBitmap(uint8_t width, uint8_t, height);
virtual ~LEDBitmap() {
free(_map.data);
};
private: //members
MapData _map;
};
因为ptr
是一个指针,所以不是。您正在尝试填充结构的字段,该结构甚至没有分配内存。这会导致 未定义的行为。
- 你应该先为结构分配内存,然后填充
它。
- 然后,在析构函数中,您必须取消分配该内存。
记住,当使用 new
时,也必须使用 delete
。通常,您希望调用 delete
的次数与调用 new
的次数完全相同。
但是为什么要用指针呢?在那种情况下,这似乎是多余的。当你没有充分理由使用指针时,你的代码容易出错。
您可以从以下建议中选择一些建议,而不是使用指针(不需要您定义构造函数):
- 使用
std::vector<uint8_t>
完成所有后台工作
(related),
正如 NathanOliver 所说。
- 使用
struct MapData
作为数据成员而不是指针。那
如果您希望重用该结构,则在 OOP 编程中有意义
例如,另一个 class。
- 如果该结构仅用于此 class,则考虑
直接给 class 结构的字段,作为它的数据
成员,而不是结构本身。
这个问题可能有点愚蠢,但我对 C++ 还是个新手,我已经有一段时间没用它做了什么了。
我有一个名为 LEDBitmap
的 class,它应该保存位图的宽度、高度和数据,只有 1 和 0。
在头文件中我有以下结构:
struct MapData
{
uint8_t width;
uint8_t height;
uint8_t[][] data;
};
以及下面的构造函数、析构函数和成员变量:
class LEDBitmap
{
public:
LEDBitmap(uint8_t width, uint8_t, height, uint8_t data[][]);
LEDBitmap(uint8_t width, uint8_t, height);
virtual ~LEDBitmap() { };
[...]
private: //members
MapData _map;
};
我现在想编写构造函数,可能还有析构函数,到目前为止,第一个构造函数如下:
//initialize an empty bitmap with only zeros in it
LEDBitmap::LEDBitmap(uint8_t width, uint8_t, height) {
_map.width = width;
_map.height = height;
_map.data = new uint8_t[width][height];
}
这个实现可行吗? (可能不会) 我应该费心去实际实现析构函数吗?
编辑:
根据@gsamaras 的建议调整了我的代码。
_map
以前是*_ptr
。
编辑: 一位朋友建议改用 calloc()
。因此我现在有:
LEDBitmap::LEDBitmap(uint8_t width, uint8_t height) {
_map.width = width;
_map.height = height;
_map.data = calloc(width*height*(sizeof(uint8_t));
}
和
class LEDBitmap
{
public:
LEDBitmap(uint8_t width, uint8_t, height, uint8_t data[][]);
LEDBitmap(uint8_t width, uint8_t, height);
virtual ~LEDBitmap() {
free(_map.data);
};
private: //members
MapData _map;
};
因为ptr
是一个指针,所以不是。您正在尝试填充结构的字段,该结构甚至没有分配内存。这会导致 未定义的行为。
- 你应该先为结构分配内存,然后填充 它。
- 然后,在析构函数中,您必须取消分配该内存。
记住,当使用 new
时,也必须使用 delete
。通常,您希望调用 delete
的次数与调用 new
的次数完全相同。
但是为什么要用指针呢?在那种情况下,这似乎是多余的。当你没有充分理由使用指针时,你的代码容易出错。
您可以从以下建议中选择一些建议,而不是使用指针(不需要您定义构造函数):
- 使用
std::vector<uint8_t>
完成所有后台工作 (related), 正如 NathanOliver 所说。 - 使用
struct MapData
作为数据成员而不是指针。那 如果您希望重用该结构,则在 OOP 编程中有意义 例如,另一个 class。 - 如果该结构仅用于此 class,则考虑 直接给 class 结构的字段,作为它的数据 成员,而不是结构本身。