Devo usare un unique_ptr con un tipo di array o un vettore?

3

Sono fuori dal C ++ da anni, l'ultima volta che l'ho usato è tornato in gamedesign prima di C ++ 11. Vedo tutti questi nuovi tipi di puntatore che sembrano grandi. Ma non sono sicuro di quando e come usarli. In passato avrei creato un buffer come questo:

uint bufferSize = 1024;
unsigned char *buffer = (unsigned char*)malloc(bufferSize, sizeof(char));

Non è bello e sono abbastanza sicuro che anche allora il nuovo / delete era già una cosa in C ++, ma non ne ho mai appreso in quel momento. Non credo che i puntatori grezzi dovrebbero essere usati se evitabili, quindi sto cercando di abituarmi a scrivere questo ora:

uint bufferSize = 1024;
std::unique_ptr<unsigned char[]> buffer;
buffer = std::make_unique<unsigned char[]>(bufferSize);

Ma questo solleva la domanda, dovrei semplicemente mappare i vecchi puntatori grezzi a unique_ptr come questo? C'è anche std::vector , che sembra un adattamento molto più naturale per qualsiasi array. Dovrei usare invece un vettore? Ci sono regole pratiche per quando usare l'una o l'altra (per gli array)?

Per aggiungere informazioni più specifiche, sto creando un gioco e sto impostando uno screenbuffer su cui disegnare, sto iniziando con ASCII e probabilmente passerò ai pixel da qualche parte in futuro. La dimensione del buffer non dovrà mai cambiare in fase di esecuzione, ma sarebbe bello poter giocare un po 'con le dimensioni dello schermo durante lo sviluppo, ecco perché non sto semplicemente dichiarando un array a lunghezza fissa (il mio bufferSize è in realtà due Sts moltiplicato; screenWidth e screenHeight). Questo è solo un prototipo, non deve essere scalabile o distribuibile, ma voglio ancora sfruttare questa possibilità per imparare a scrivere meglio il C ++.

    
posta Kevin 17.10.2018 - 15:09
fonte

2 risposte

4

sizeof(TYPE) è stata una pessima idea in C e C ++ da sempre, supponendo che potresti usare sizeof *pointer . Il problema è che duplica le informazioni sul tipo senza aggiungere un controllo.

In C, lanciare un void* è anche una cattiva idea, poiché la modifica della lingua dovrebbe essere eseguita solo dove e quando necessario, dopo un'attenta considerazione.

Successivamente, questo:

uint bufferSize = 1024;
unsigned char *buffer = (unsigned char*)malloc(bufferSize, sizeof(char));

Non è del tutto equivalente al seguente, salvo l'allocatore utilizzato e la gestione automatica del buffer:

uint bufferSize = 1024;
auto buffer = std::make_unique<unsigned char[]>(bufferSize);

La differenza addizionale è l'inizializzazione del valore, il secondo lo fa, l'ex si astiene da esso.

È significativo?
Non possiamo dire, dipende dalle circostanze specifiche. Forse vuoi davvero quell'inizializzazione, o il compilatore può ottimizzarlo.

O forse il seguente corrisponde alle tue esigenze migliori:

uint bufferSize = 1024;
std::unique_ptr<unsigned char[]> buffer(new unsigned char[bufferSize]);

Ad ogni modo, a meno che non si usi qualcosa come sopra, o si debba passare il buffer al codice che si aspetta un new ed up buffer, std::vector è probabilmente più semplice e può essere ottimizzato fino allo stesso codice.

    
risposta data 17.10.2018 - 15:57
fonte
2

Sì, dovresti usare std::vector<unsigned char> per un buffer di dimensioni staticamente sconosciute. Tu puoi usare anche una std::array<unsigned char, SIZE> per un buffer di dimensioni staticamente conosciute, ma non ne hai anche tu. Non utilizzare std::unique_ptr<unsigned char[]> , new o malloc .

Potrebbe valere la pena di dichiarare un alias di tipo se vai per array

constexpr uint ScreenWidth = 1920;
constexpr uint ScreenHeight = 1080;

using ScreenBuffer = std::array<unsigned char, ScreenWidth * ScreenHeight>;

Un vettore è abbastanza facile da usare.

std::vector<unsigned char> buffer(ScreenWidth * ScreenHeight);
// use buffer.data() as you would previously use a unsigned char *
    
risposta data 17.10.2018 - 17:55
fonte

Leggi altre domande sui tag