2009-12-16 22 views
16

Come si può convertire un shared_ptr che punta a un oggetto const su un parametro shared_ptr che punta a un oggetto non const. Sto cercando di fare quanto segue:const shared_ptr to shared_ptr

boost::shared_ptr<const A> Ckk(new A(4)); 

boost::shared_ptr<A> kk=const_cast< boost::shared_ptr<A> > Ckk; 

Ma non funziona.

risposta

30

'boost :: const_pointer_cast' farà quello che stai chiedendo, ma l'obbligatorio seconda metà della risposta è che probabilmente non dovresti usarlo. Il 99% delle volte in cui sembra che sia necessario eliminare la proprietà const di una variabile, significa che si dispone di un difetto di progettazione. Const è a volte più di una semplice vetrina e gettarlo via può portare a bug inaspettati.

Senza conoscere più dettagli della situazione, non si può dire con certezza. Ma nessuna discussione sul const-cast è completa senza menzionare questo fatto.

+2

+1 che const è lì per una ragione. può essere. –

+1

L'uso di 'const_pointer_cast' non è un difetto di progettazione molto più spesso di quanto tu pensi. Ad esempio, i contenitori standard possono operare solo con tipi che sono convertibili al tipo degli elementi contenuti. Quindi il seguente non è possibile anche se è logicamente corretto: 'vector > cont; shared_ptr a; cont.push_back (a); ' –

+10

@ jons34yp: Non c'è nulla di logicamente corretto a riguardo. Ti è stato dato un puntatore _const_; ciò significa che non sei autorizzato a usarlo in modo non costante. Se si dispone di un elenco di puntatori non const e si desidera inserire un puntatore const in esso, difficile. Con la sua const-casting, stai violando un contratto con la persona che ti ha dato quel puntatore (che è il contratto che non dovresti cambiarlo). Questo è vero anche per i puntatori regolari come shared_ptr's. –

2

il modo corretto dovrebbe essere questo

boost::shared_ptr<A> kk (boost::const_pointer_cast<A>(Ckk)); 
2

std::const_cast_pointer rende un secondo puntatore gestito. Dopo il cast hai un puntatore scrivibile e il puntatore const originale. Il pointee rimane lo stesso. Il conteggio dei riferimenti è stato aumentato di 1.

Si noti che const_cast è una parola chiave incorporata, ma const_pointer_cast è una funzione di modello nello spazio dei nomi std.

Il puntatore scrivibile può quindi essere utilizzato per modificare il valore da sotto shared_ptr<const T>. IMHO il puntatore scrivibile dovrebbe persistere temporaneamente sullo stack; altrimenti ci deve essere un difetto di progettazione.

Una volta ho scritto un piccolo programma di test per rendere questo chiaro a me stesso che ho adattato per questa discussione:

#include <memory> 
#include <iostream> 
#include <cassert> 

using namespace std; 

typedef shared_ptr<int> int_ptr; 
typedef shared_ptr<const int> const_int_ptr; 

int main(void) 
{ 
    const_int_ptr Ckk(new int(1)); 

    assert(Ckk.use_count() == 1); 
    cout << "Ckk = " << *Ckk << endl; 

    int_ptr kk = const_pointer_cast<int>(Ckk); // obtain a 2nd reference 
    *kk = 2;     // change value under the const pointer 

    assert(Ckk.use_count() == 2); 
    cout << "Ckk = " << *Ckk << endl;  // prints 3 
} 

Sotto Unix o Windows/Cygwin, compilare con

g++ -std=c++0x -lm const_pointer_cast.cpp 
+0

"stampa 3" - da dove viene il 3? È un errore di battitura? –

Problemi correlati