我正在为Arduinos编写代码,所以我从未使用过std::vector
,因为Arduinos不支持它。
我想要一个分段可定制的LED条,每个部分都应该由自己的对象表示。固定的最大节数是可以的,所以我不需要动态大小的数组。
据我所知,我有三个选项可以实现这一点。为了演示,我使用了这个类:
#include<iostream>
using namespace std;
class Test {
private:
int var = 0;
public:
Test () {}
Test(int input) {
var = input;
}
~Test() {
cout << "Instance with var = " << var << " deleted" << endl;
}
void printTest() {
cout << "var = " << var << endl;
}
};
选项1:用new
填充的指针数组。
int main() {
int maxTest = 10;
Test* test[maxTest];
test[0] = new Test(10);
test[0]->printTest();
delete test[0];
return 0;
}
输出:
var = 10
Instance with var = 10 deleted
这似乎是大多数人推荐的"标准"方式,但我不喜欢不能使用delete[]
,而是必须单独删除每个实例。这尤其令人讨厌,因为尝试delete
一个尚未初始化的对象会使程序崩溃(至少对我来说,没有错误/异常,执行只是停止(。所以我不能只说for(int i; i<maxTest; i++) delete test[i];
,而是必须分别跟踪每个对象的数量和位置,因为当填充test[0]
到test[2]
时,我仍然需要能够删除test[1]
。
选项2:使用new
初始化阵列。
int main() {
int maxTest = 10;
Test* test = new Test[maxTest];
test[0] = Test(10);
test[0].printTest();
delete[] test;
return 0;
}
输出:
Instance with var = 10 deleted
var = 10
Instance with var = 0 deleted
Instance with var = 0 deleted
Instance with var = 0 deleted
Instance with var = 0 deleted
Instance with var = 0 deleted
Instance with var = 0 deleted
Instance with var = 0 deleted
Instance with var = 0 deleted
Instance with var = 0 deleted
Instance with var = 10 deleted
我也经常看到这个选项,但是在这里,实例化特定对象(如test[0] = Test(10);
(显然会导致首先调用析构函数。这对我来说是有意义的,因为我认为初始化数组后位于test[0]
的实例需要首先删除,但为什么这个实例的var
等于10而不是0(请参阅输出的第一行(?如果不处理析构函数,我就无法真正使用它,因为在我不希望调用它的时候,析构函数会被调用,而我希望避免这种情况。此外,无论我实际想要使用的maxTest
实例有多少,都让它处于活动状态,这感觉效率很低。
选项3:完全丢弃指针,与选项2的问题相同,感觉不对。
int main() {
int maxTest = 10;
Test test[maxTest];
test[0] = Test(10);
test[0].printTest();
return 0;
}
输出与选项2相同。
撇开上面提到的问题不谈,我想知道为什么我在任何地方都看不到这个建议,也许有人可以解释一下?只要有足够的内存可以将数据保存在堆栈中(在像Arduino这样的封闭系统中应该可以知道(,这就没有错,对吧?
我是否错过了另一种有用的实现方式?你将如何实现这一目标,为什么?感谢所有的意见!干杯
首先,C++官方不支持可变长度数组!它们是一个可选的C特性(自C11以来(,从未集成在C++中,因为它是析构函数和异常处理的噩梦。
这是合法的C++:
...
int main() {
constexpr int maxTest = 10;
Test test[maxTest] = {Test(10)};
test[0].printTest();
return 0;
}
正如预期的那样:
var = 10
Instance with var = 0 deleted
Instance with var = 0 deleted
Instance with var = 0 deleted
Instance with var = 0 deleted
Instance with var = 0 deleted
Instance with var = 0 deleted
Instance with var = 0 deleted
Instance with var = 0 deleted
Instance with var = 0 deleted
Instance with var = 10 deleted
因为您现在定义了一个真正的自动数组,为它的第一个元素提供自定义初始化,并让编译器默认初始化其他元素。
当数组超出范围时,编译器会温和地删除数组及其元素。当然,数组的所有元素都会在启动时初始化,并在程序结束时销毁,无论您真正想使用多少。。。
如果你真的想使用可变数量的对象,只在需要时创建它们,然后在一次操作中去掉所有对象,你必须使用向量。如果std::vector
在Arduino上不可用,您可以提供自己的实现。您需要:
- 已分配的指针数组
- 数组中的当前元素数
- 在数组末尾构造新元素的函数
- 将首先销毁其现有元素的析构函数
- 删除复制/移动构造函数和赋值运算符(如果不需要的话((五条规则(
- 可选地,删除最后一个元素的方法
可能比尝试使用非平凡数据的可变长度数组更简单、更健壮。。。