Alokasikan memori objek secara statis; merintisasinya secara dinamis?


9

Saya memiliki objek yang konstruktornya akan melewati parameter. Jika saya tahu nilai parameter pada waktu kompilasi, saya dapat membuat objek secara statis:

static FOOOBJ foo(3);

(Saya mengerti bahwa itu tidak benar-benar dilakukan secara statis, yaitu oleh kompiler, tetapi sebenarnya dilakukan selama pengaturan).

Tetapi jika saya tidak tahu nilai parameter pada waktu kompilasi, saya masih ingin pra-mengalokasikan ruang untuk objek tetapi membangun objek di ruang itu pada saat run time. Bisakah itu dilakukan tanpa .initialize()metode terpisah ?

Jawaban:


3

Menggunakan initialize()metode untuk kelas bertentangan dengan prinsip konstruktor kelas, yaitu sekali instance kelas telah dibangun , itu harus " siap digunakan ".

Seperti yang disarankan oleh jawaban Ignacio, sintaksis penempatan C ++ jauh lebih baik untuk tujuan Anda.

Namun, dengan perpustakaan Arduino, sintaksis penempatan tidak didukung "out of the box", jadi Anda harus menerapkannya sendiri; jangan takut, itu cukup mudah:

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

Sintaksis penempatan dapat menjadi binatang yang rumit di C ++, tetapi untuk tujuan spesifik Anda, penggunaannya bisa agak sederhana:

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

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

Perbedaannya dengan kode Anda saat ini fooadalah sekarang menjadi pointer, karenanya panggilan metode apa pun akan digunakan ->sebagai ganti ..

Jika Anda benar-benar ingin terus menggunakan foosebagai instance dan bukan pointer, maka Anda dapat melakukannya (tapi saya tidak menyarankannya seperti yang dijelaskan nanti) dengan menggunakan referensi sebagai gantinya:

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

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

Masalah dengan kode ini, adalah Anda tidak bisa tahu apakah foosudah dibangun dengan FOOOBJinstance nyata atau tidak; menggunakan pointer, Anda selalu dapat memeriksa apakah itu benar 0atau tidak.

Menggunakan sintaksis penempatan, Anda harus sadar bahwa Anda tidak dapat deletemembuat fooinstance di atas. Jika Anda ingin menghancurkan foo(yaitu memastikan bahwa destruktornya disebut), maka Anda harus secara eksplisit memanggil destruktor:

foo->~FOOOBJ();

1
Saya tidak mengetahui sintaksnya tetapi itu masuk akal! Apakah konstruktor perlu mengetahui / dirancang untuk itu? FOOOBJadalah objek OneWire, menggunakan perpustakaan Jim Studt (v2.2). Saya menerima pesan error: no matching function for call to 'operator new(unsigned int, byte [14])'melalui newtelepon. Sepertinya avr-g ++ mungkin tidak mengerti sintaks.
JRobert

Ya, Anda benar, saya menggunakan Eclipse untuk proyek Arduino saya dan apa yang saya periksa, tampaknya berhasil, kecuali bahwa yang berhasil adalah kompilasi Eclipse C ++, bukan avr-g ++! Saya telah mengedit jawaban saya untuk menunjukkan solusi sederhana.
jfpoilpret

Mengenai pertanyaan Anda tentang konstruktor, tidak ada persyaratan khusus, tetapi jika konstruktor itu sendiri melakukan alokasi dinamis, maka penempatan baru tidak akan mencegahnya.
jfpoilpret

Saya juga menggunakan Eclipse - dengan kompiler C ++ apa Anda dikonfigurasi? Plus melihat konstruktor OneWire, itu tidak newapa - apa, itu hanya menginisialisasi beberapa i / o.
JRobert

Saya menggunakan plugin Eclipse with eclipse.baeyens.it (yang menggunakan alat Arduino IDE, yaitu avr-g ++ + Arduino libs); tetapi kompilasi C ++ terjadi saat itu juga dengan Eclipse C ++, dan hanya menggunakan avr-g ++ saat meluncurkan Arduino build. Saya belum memeriksa langkah terakhir pada awalnya.
jfpoilpret

4

Anda dapat menggunakan sintaksis penempatan untuk menentukan alokasi yang ada untuk instantiate kelas.

FOOOBJ foo(0);

 ...

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

Saya menyarankan untuk mengganti deklarasi foodengan char foo[sizeof FOOOBJ];sehingga FOOOBJkonstruktor tidak dipanggil fooyang bisa menjadi masalah nyata tergantung pada apa yang konstruktor lakukan.
jfpoilpret
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.