2009-11-13 9 views
5

Esiste un modo per trasferire la proprietà dei dati contenuti in un vettore std :: (indicato da, ad esempio T * dati) in un altro costrutto, impedendo di avere "dati" diventare un puntatore penzolante dopo che il vettore è andato fuori portata?impedendo che i dati vengano liberati quando il vettore non rientra nell'ambito di applicazione

MODIFICA: NON VOGLIO COPIARE I DATI (che sarebbe una soluzione facile ma inefficace).

In particolare, mi piacerebbe avere qualcosa di simile:

template<typename T> 
    T* transfer_ownership(vector<T>&v){ 
    T*data=&v[0]; 
    v.clear(); 
    ...//<--I'd like to make v's capacity 0 without freeing data 
} 

int main(){ 
    T*data=NULL; 
    { 
     vector<double>v; 
     ...//grow v dynamically 
     data=transfer_ownership<double>(v); 
    } 
    ...//do something useful with data (user responsible for freeing it later) 
    // for example mxSetData(mxArray*A,double*data) from matlab's C interface 
} 

L'unica cosa che mi viene in mente per emulare questo è:

{ 
    vector<double>*v=new vector<double>(); 
    //grow *v... 
    data=(*v)[0]; 
} 

e poi saranno successivamente essere sia liberato i dati o (nel mio caso) usato come mxSetData (mxArray A, doppio dati). Tuttavia questo si traduce in una piccola perdita di memoria (struttura dei dati per la gestione della capacità di V, dimensioni, ecc ... ma non i dati stessi, ovviamente).

E 'possibile senza perdite?

+0

Questo è piuttosto confuso. Inoltre, prova a chiedere in un forum C++. – Nzbuu

+0

mxSetData e mxArray fanno parte dell'interfaccia MATlab C (tramite file C mess). – spirov

+0

Sì, ma non è proprio una domanda Matlab * * - Le persone che conoscono Matlab venire qui per aiutarti non saranno in grado di contribuire a nulla a meno che non conoscano il C++. – quark

risposta

0

Qualcosa come questo funziona per te?

int main() 
{ 
    double *data = 0; 
    { 
     vector<double> foo; 
     // insert some elements to foo 

     data = new double[foo.size()]; 
     std::copy(foo.begin(), foo.end(), &data[0]); 
    } 

    // Pass data to Matlab function. 
    delete [] data; 
    return 0; 
} 
5

Una soluzione semplice sarebbe scambiando il vettore con quello che si proprietario:

vector<double> myown; 

vector<double> someoneelses = foo(); 

std::swap(myown, someoneelses); 

Un approccio più duro ma forse migliore è scrivere il proprio allocatore per il vettore, e lasciarlo allocare su un pool tu mantenga. Nessuna esperienza personale, ma non è troppo complicata.

+0

Semplice, "pulito" e molto efficace dalla soluzione prospettiva perfomance. myown può essere creato su heap o da qualche altra parte, al fine di vivere dopo che qualcuno è fuori dal campo di applicazione. –

+1

o anche più breve: 'foo(). Swap (myown);' – sellibitze

+0

Grazie per aver segnalato gli allocatori personalizzati. Ho ereditato l'allocatore in un allocator_derived con un comportamento personalizzato (facendo attenzione a non cancellare se qualche flag è impostato dall'utente, cioè appena prima di rilasciare il vettore). Funziona alla grande e non perde con una certa attenzione ... su alcuni sistemi, ma non tutti purtroppo. Ad esempio funziona su mac (gcc 4.2.1) ma su Linux a 64 bit (gcc 4.3), il vettore dichiarato come vettore > non sembra nemmeno utilizzare il comportamento derivato; Non sono sicuro del perché. – spirov

1

Se il vettore contiene valori, è possibile solo copiarli (cosa che accade quando si chiama std :: copy, std :: swap, ecc.). Se si conservano oggetti non primitivi in ​​un vettore e non si desidera copiarli (e utilizzarli in un'altra struttura dati), prendere in considerazione la memorizzazione dei puntatori

5

Il punto di utilizzo di un vettore std :: non deve preoccuparsi di i dati al suo interno:

  • Mantieni il tuo vettore per tutta la tua applicazione;
  • Passa con le altre funzioni (per evitare copie non necessarie);
  • E le funzioni di avanzamento prevedono un puntatore a T con &v[0].

Se davvero non si vuole mantenere il vostro vettore, si dovrà copiare i dati - non è possibile trasferire la proprietà a causa std::vector garantisce distruggerà il suo contenuto quando si va fuori dal campo di applicazione. In tal caso, utilizzare l'algoritmo std::copy().

+1

+1 per aver menzionato il costrutto '& v [0]' per la compatibilità con l'interfaccia C-like. –

+0

Il terzo elemento è la chiave, perché passare il contenuto del vettore alle funzioni esterne senza copiare è una grande parte di ciò che l'OP vuole. – quark

-2

Poiché non si desidera copiare i dati tra contenitori, ma si desidera trasferire la proprietà dei dati tra contenitori, suggerisco di utilizzare un contenitore di puntatori intelligenti come segue.

void f() 
{ 
    std::vector<boost::shared_ptr<double> > doubles; 
    InitVector(doubles); 

    std::vector<boost::shared_ptr<double> > newDoubles(doubles); 
} 

Davvero non si può trasferire la proprietà dei dati tra contenitori standard senza fare una copia di esso, in quanto contenitori standard copiare sempre i dati che incapsulano. Se si desidera ridurre al minimo il sovraccarico di copia di oggetti costosi, è consigliabile utilizzare un puntatore intelligente conteggiato con riferimento per avvolgere la struttura dei dati costosi.boost::shared_ptr è adatto per questo compito poiché è abbastanza economico fare una copia di esso.

Problemi correlati