Allocare staticamente la memoria degli oggetti; inizializzarlo in modo dinamico?


9

Ho un oggetto il cui costruttore riceve un parametro. Se conosco il valore del parametro al momento della compilazione, posso costruire l'oggetto staticamente:

static FOOOBJ foo(3);

(Capisco che non è realmente fatto staticamente, cioè dal compilatore, ma è effettivamente fatto durante l'installazione).

Ma se non conosco il valore del parametro in fase di compilazione, mi piacerebbe comunque pre-allocare spazio per l'oggetto, ma costruire l'oggetto in quello spazio in fase di esecuzione. Può essere fatto senza un .initialize()metodo separato ?

Risposte:


3

L'uso di un initialize()metodo in una classe è contrario al principio di un costruttore di classi, cioè una volta che un'istanza di classe è stata costruita , dovrebbe essere " pronta per l'uso ".

Come suggerito dalla risposta di Ignacio, la sintassi del posizionamento C ++ è molto migliore per il tuo scopo.

Tuttavia, con le librerie Arduino, la sintassi del posizionamento non è supportata "out of the box", quindi è necessario implementarla da soli; non temere, è abbastanza semplice:

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

La sintassi del posizionamento può essere una bestia complessa in C ++, ma per il tuo scopo specifico, il suo utilizzo può essere piuttosto semplice:

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

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

La differenza con il tuo codice attuale è che fooora è un puntatore, quindi qualsiasi chiamata al metodo utilizzerà ->invece di ..

Se vuoi assolutamente continuare a utilizzare foocome istanza e non come puntatore, puoi farlo (ma non lo consiglio come spiegato più avanti) usando invece un riferimento :

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

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

Il problema con questo codice è che non puoi sapere se fooè già stato costruito con FOOOBJun'istanza reale oppure no; usando un puntatore, puoi sempre verificare se lo è 0o meno.

Utilizzando la sintassi del posizionamento, devi essere consapevole del fatto che non è possibile deletel' fooistanza sopra. Se vuoi distruggere foo(cioè assicurati che venga chiamato il suo distruttore), devi chiamare esplicitamente il distruttore:

foo->~FOOOBJ();

1
Non ero a conoscenza della sintassi ma questo ha perfettamente senso! Il costruttore deve essere a conoscenza / progettato per questo? FOOOBJè un oggetto OneWire, usando la libreria di Jim Studt (v2.2). Ricevo il messaggio error: no matching function for call to 'operator new(unsigned int, byte [14])'sulla newchiamata. Sembra che avr-g ++ potrebbe non capire la sintassi.
JRobert

Sì, hai ragione, sto usando Eclipse per i miei progetti Arduino e quello che ho controllato, sembrava funzionare, tranne per il fatto che ciò che ha funzionato era la compilazione Eclipse C ++, non avr-g ++! Ho modificato la mia risposta per mostrare una soluzione semplice.
jfpoilpret,

Per quanto riguarda la tua domanda sul costruttore, non esiste un requisito specifico, ma se il costruttore stesso esegue l'allocazione dinamica, il posizionamento nuovo non lo impedirà.
jfpoilpret,

Sto anche usando Eclipse - con quale compilatore C ++ è configurato il tuo? Inoltre, guardando al costruttore OneWire, non fa newnulla, inizializza solo un po 'di I / O.
JRobert

Sto usando Eclipse con il plugin eclipse.baeyens.it (che utilizza gli strumenti IDE di Arduino, ovvero avr-g ++ + librerie Arduino); ma la compilazione C ++ avviene al volo con Eclipse C ++ e usa avr-g ++ solo quando si avvia la build di Arduino. Inizialmente non avevo verificato quest'ultimo passaggio.
jfpoilpret,

4

È possibile utilizzare la sintassi del posizionamento per specificare un'allocazione esistente in cui creare un'istanza della classe.

FOOOBJ foo(0);

 ...

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

Suggerirei di sostituire la dichiarazione di foocon in char foo[sizeof FOOOBJ];modo che il FOOOBJcostruttore non venga richiesto, il fooche potrebbe essere un vero problema a seconda di ciò che fa il costruttore.
jfpoilpret,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.