オブジェクトメモリを静的に割り当てます。動的に初期化しますか?


9

コンストラクターがパラメーターを渡されるオブジェクトがあります。コンパイル時にパラメーター値がわかっている場合は、オブジェクトを静的に構築できます。

static FOOOBJ foo(3);

(それは実際には静的に、つまりコンパイラーによって行われるのではなく、実際にセットアップ中に行われることを理解しています)。

しかし、コンパイル時にパラメーター値がわからない場合でも、オブジェクトにスペースを事前に割り当てておきますが、実行時にそのスペースにオブジェクトを構築します。別の.initialize()方法なしでそれを行うことができますか?

回答:


3

initialize()メソッドをクラスに使用することは、クラスコンストラクターの原則に反します。つまり、クラスインスタンスが構築されると、「使用する準備ができている」はずです。

イグナシオの回答で示唆されているように、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
私は構文を知りませんでしたが、それは完全に理にかなっています!コンストラクタはそれを意識する必要がありますか?FOOOBJJim Studtのライブラリ(v2.2)を使用するOneWireオブジェクトです。通話中にメッセージが表示さerror: no matching function for call to 'operator new(unsigned int, byte [14])'newます。avr-g ++が構文を理解できないようです。
JRobert、2014年

はい、そうです、私はArduinoプロジェクトにEclipseを使用しています。私がそれを確認したところ、動作したようですが、動作したのはEclipse C ++コンパイルであり、avr-g ++ではありませんでした。簡単な回避策を示すために回答を編集しました。
jfpoilpret 2014年

コンストラクターに関する質問に関しては、それは特定の要件ではありませんが、コンストラクター自体が動的割り当てを実行する場合、新しい配置はそれを妨げません。
jfpoilpret 2014年

私はEclipseも使用しています-どのC ++コンパイラで構成されていますか?さらに、OneWireコンストラクターを見ると、new何もせず、一部の入出力を初期化するだけです。
JRobert、2014年

私はeclipse.baeyens.itプラグイン(Arduino IDEツール、つまりavr-g ++ + Arduino libsを使用)を備えたEclipse を使用しています。ただし、C ++コンパイルはEclipse C ++でオンザフライで行われ、Arduinoビルドの起動時にのみavr-g ++を使用します。最初は後者のステップをチェックしていませんでした。
jfpoilpret 2014年

4

配置構文を使用して、クラスをインスタンス化する既存の割り当てを指定できます。

FOOOBJ foo(0);

 ...

  FOOOBJ *f = new (foo) FOOOBJ(3);

私はの宣言を交換することをお勧めしたいfoochar foo[sizeof FOOOBJ];なるようにFOOOBJコンストラクタがために呼び出されませんfooコンストラクタが何をするかに応じて、実際の問題になる可能性があります。
jfpoilpret 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.