In questo caso, la struttura delle impostazioni e l'oggetto che si desidera costruire con tali impostazioni condividono la stessa durata: la durata di una chiamata a theFunction
. Quindi l'opzione migliore è probabilmente la più semplice: non preoccupatevi nemmeno di dare loro variabili separate in primo luogo. Nel moderno C ++, potrebbe essere conciso come:
MyClass mClass({ /* struct arguments */ });
Non solo è più conciso, ma è potenzialmente più efficiente. Poiché la struct è un temporaneo senza nome, vive solo per la durata di questa chiamata del costruttore, il che significa che almeno in teoria può tranquillamente essere spostato nel costruttore mClass
anziché copiato.
Inoltre, dovresti fare in modo che il costruttore MyClass prenda le impostazioni struct per riferimento (se possibile, const riferimento). Fare passare per valore di solito costringe una copia, che sembra completamente inutile in questo caso.
In generale, potrebbe non essere così semplice, e le varie domande che aggiungi alla fine implicano un consiglio leggermente più generale.
I don't know the proper design for this sort of message passing in C++ I am not used to manual memory management coming from a managed language background. What is the standard way to handle this struct full of settings?
La cosa importante da capire è che nel C ++ moderno, non dovresti quasi mai gestire la memoria manualmente . In particolare, quasi sempre si vogliono usare variabili allocate nello stack o puntatori intelligenti alle variabili allocate su heap invece dei puntatori "grezzi" e si preferisce quasi sempre lavorare con le classi che implementano RAII (cioè hanno distruttori che puliscono correttamente su di sé) invece di affidarsi alle coppie "nude" nuove / eliminate.
In particolare, se non hai bisogno di mClass
per essere un puntatore (sia raw che smart), non rendine uno.
MyClass mClass; // doesn't get any simpler than this
Se hai davvero bisogno che sia un puntatore, usa un puntatore intelligente per assicurarti che venga pulito correttamente, qualunque cosa accada.
// the 'auto' is deduced to be 'std::unique_ptr<MyClass>'
auto mClass = std::make_unique<MyClass>(MyStruct{ /* struct arguments */ });
Il tuo puntatore intelligente dovrebbe essere std::unique_ptr
poiché (di solito) ha un sovraccarico di runtime pari a zero rispetto a un puntatore non elaborato, applica una proprietà univoca non consentendo di copiarlo (che di solito è ciò che desideri), e può essere facilmente convertito in altri puntatori intelligenti come std::shared_ptr
se hai bisogno di un comportamento più complicato.
Entrambe queste opzioni garantiscono che l'oggetto mClass
venga distrutto e deallocato anche in presenza di eccezioni o di ritorni anticipati. Non devi mai scrivere un esplicito "per favore distruggi questo ora" in qualsiasi parte del tuo codice.
Consiglio vivamente di leggere Effective Modern C ++ per ulteriori dettagli su questi argomenti.
Or maybe instead or initializing the struct on the stack I just do a heap allocation and clean up the struct in the class destructor.
Questo è del tutto possibile, ma eccessivamente complicato e un po 'inutile.