2015-11-13 3 views
5

SfondoUtilizzando un puntatore intelligente per gestire la memoria allocata all'interno funzione

Se avevo una funzione foo come segue

void foo(std::vector<int>& values) 
{ 
    values = std::vector<int>(10, 1); 
} 

Poi ho potuto chiamare come

std::vector<int> values; 
foo(values); 

noti che l'iniziale vector è vuoto, quindi viene popolato all'interno della funzione foo.

Spesso mi imbatto in interfacce che io non posso cambiare (cioè 3a parte), che hanno lo stesso intento come sopra, ma utilizzando le matrici prime, ad esempio

void foo(int*& values) 
{ 
    values = new int[10]; 
    std::fill_n(values, 10, 1); 
} 

Il mio problema con questi è che ora io sono responsabile della gestione di quella memoria, ad es

int* values; 
foo(values); 
delete[] values; 

Domanda

Esiste un modo posso usare puntatori intelligenti per gestire questa memoria per me? Mi piacerebbe fare qualcosa di simile

std::unique_ptr<int[]> values; 
foo(values.get()); 

ma get restituisce un puntatore che è un R-valore, quindi non posso passare per riferimento non-const.

+1

Non so se questo è legale, ma lo fa compilo: http://coliru.stacked-crooked.com/a/860ae38fd2cdb4a2 – NathanOliver

risposta

2
  1. Crea vuoto unique_ptr.
  2. Crea puntatore.
  3. Passa il puntatore alla funzione.
  4. Reimposta unique_ptr su quel puntatore.

Come quella:

std::unique_ptr<int[]> values; 
int* values_ptr; 
foo(values_ptr); 
values.reset(values_ptr); 

Oppure:

int* values_ptr; 
foo(values_ptr); 
std::unique_ptr<int[]> values(values_ptr); 
+0

Si potrebbe anche usare 'make_unique' – Gabriel

+0

Coz è 2015 ... – Gabriel

+0

Infatti make_unique costruisce la cosa stessa, non puoi dargli un puntatore o puoi? – Gabriel

1

Risposta semplice: non si può. Ma credo che ci sia un modo per semplificarti la vita. Dato che fai sempre la stessa cosa, devi semplicemente scrivere una funzione che fa per te e chiama quella funzione quando ti serve. Dato che suppongo che tu voglia usare il valore restituito scritto in memoria prima di rilasciarlo, faccio in modo che la mia funzione lo restituisca.

template <typename T, typename Function> 
std::unique_ptr<T[]> call(Function f) { 
    T * value; 
    f(value); 
    return { value }; 
} 

// then to use it 
auto value = call<int>(foo); 

Questo ti soddisfa?

La funzione può essere migliorata per rilevare la differenza di puntatori a un oggetto o a un array se necessario, e potrebbe anche essere migliorata per rilevare automaticamente il tipo di parametro necessario in modo da non doverlo digitare .