静态分配对象内存;动态地初始化它?


9

我有一个对象,其构造函数被传递了一个参数。如果在编译时知道参数值,则可以静态构造对象:

static FOOOBJ foo(3);

(我知道这并不是真正地静态完成,即由编译器完成,但实际上是在安装过程中完成的)。

但是,如果我在编译时不知道参数值,我仍然想为对象预分配空间,但在运行时在该空间中构造对象。没有单独的.initialize()方法可以做到吗?

Answers:


3

使用initialize()一类方法是相反的一类构造函数的原则,即一旦一个类的实例已经被构建,它应该是“ 准备使用 ”。

正如Ignacio的答案所建议的,C ++放置语法对您的目的要好得多。

但是,对于Arduino库,“开箱即用”不支持放置语法,因此您必须自己实现它。不要害怕,这很简单:

void* operator new(size_t size, void* ptr)
{
    return ptr;
}

放置语法在C ++中可能是一个复杂的野兽,但是出于您的特定目的,它的用法可能非常简单:

static char buffer[sizeof FOOOBJ];
static FOOOBJ* foo;

void setup() {
    ...
    foo = new (buffer) FOOOBJ(3);
    ...
}

您当前代码的区别foo在于现在是一个指针,因此任何方法调用都将使用->代替.

如果您绝对要继续使用foo实例而不是指针,则可以使用引用来做到这一点(但我不建议稍后再解释):

static char buffer[sizeof FOOOBJ];
static FOOOBJ& foo = *((FOOOBJ*) buffer);

void setup() {
    ...
    new (buffer) FOOOBJ(3);
    ...
}

这段代码的问题是,您不知道是否foo已经使用真实FOOOBJ实例进行了构造。使用指针,您始终可以检查它是否0存在。

使用放置语法,必须注意您不能delete使用foo上面的实例。如果要销毁foo(即确保已调用其析构函数),则必须显式调用析构函数:

foo->~FOOOBJ();

1
我不知道语法,但这完全有意义!构造函数是否需要了解/为其设计?FOOOBJ是使用Jim Studt的库(v2.2)的OneWire对象。我error: no matching function for call to 'operator new(unsigned int, byte [14])'new通话中收到消息。看来AVR-G ++可能不懂语法。
JRobert

是的,您是对的,我在Arduino项目中使用了Eclipse,并且对其进行了检查,但似乎可以正常工作,只是有效的是Eclipse C ++编译,而不是avr-g ++!我已经编辑了答案,以显示一个简单的解决方法。
jfpoilpret 2014年

关于构造函数的问题,没有特别要求,但是如果构造函数本身执行动态分配,则new放置不会阻止它。
jfpoilpret 2014年

我也在使用Eclipse-为您的C ++编译器配置了什么?再来看一下OneWire构造函数,它什么也没有new,它只是初始化一些I / O。
JRobert

我正在使用带有eclipse.baeyens.it插件的Eclipse (它使用Arduino IDE工具,即avr-g ++ + Arduino库);但是C ++编译是通过Eclipse C ++即时进行的,并且仅在启动Arduino构建时才使用avr-g ++。最初我没有检查后一步。
jfpoilpret 2014年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.