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.