在没有std::vector的情况下生成对象数组的每种方法都有什么含义



我正在为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上不可用,您可以提供自己的实现。您需要:

  • 已分配的指针数组
  • 数组中的当前元素数
  • 在数组末尾构造新元素的函数
  • 将首先销毁其现有元素的析构函数
  • 删除复制/移动构造函数和赋值运算符(如果不需要的话((五条规则(
  • 可选地,删除最后一个元素的方法

可能比尝试使用非平凡数据的可变长度数组更简单、更健壮。。。

相关内容

最新更新