Sono un novizio C++ relativo che tenta di convertire un progetto esistente da puntatori grezzi, con un complicato protocollo di gestione della memoria, fino all'uso di C++ 11 shared_ptr
. Nel complesso sta andando molto bene, e io penso Capisco come lo shared_ptr
funzioni in termini di semantica del movimento, riferimenti di valore, ecc. Roba buona.Errore strano nel tentativo di eseguire un shared_ptr swap()
Tuttavia, ho riscontrato un errore strano che non capisco e non so come risolvere. Prima un po 'di storia. Ho una gerarchia di classi radicata in una classe base astratta denominata EidosValue
, e una classe denominata EidosValue_Int_vector
è (indirettamente) una sottoclasse concreta di che:
class EidosValue
class EidosValue_Int : public EidosValue
class EidosValue_Int_vector : public EidosValue_Int
Il mio codice trasporti a generalmente EidosValue
, ma a volte, soprattutto quando si crea un nuovo valore, ho bisogno di gestire una sottoclasse specifica.
ho fatto typedef per le shared_ptr
s per queste classi, in modo da avere:
typedef std::shared_ptr<EidosValue> EidosValue_SP;
typedef std::shared_ptr<EidosValue_Int_vector> EidosValue_Int_vector_SP;
tra gli altri. OK, quindi ora al centro del problema. Ho una funzione che restituisce un EidosValue_SP
che crea. A seconda della logica all'interno della funzione, potrebbe creare una delle diverse sottoclassi concrete di EidosValue
. Così faccio qualcosa di simile:
EidosValue_SP MyClass::MyMethod(...)
{
EidosValue_SP result;
if (...)
{
EidosValue_Int_vector_SP int_result_SP = make_shared<EidosValue_Int_vector>();
... do subclass-specific stuff with int_result_SP...
result.swap(int_result_SP);
}
else (...)
{
...similar logic for other subclasses...
}
...other shared logic...
return result;
}
Il problema è con la chiamata swap()
. Viene visualizzato un messaggio di errore: "Non-const lvalue reference to type 'shared_ptr<EidosValue>' cannot bind to a value of unrelated type 'shared_ptr<EidosValue_Int_vector>'
". Questo è sconcertante dal momento che EidosValue_Int_vector
non è un "tipo non correlato", è una sottoclasse pubblica di EidosValue, e il codice qui lo sa. Se scrivo result = make_shared<EidosValue_Int_vector>();
, il compilatore non ha alcun problema con quello, quindi sa chiaramente che i tipi sono correlati e compatibili. Semplicemente non mi piace nel contesto di swap()
per qualche motivo. In altri punti del mio progetto sono stato in grado di fare semplicemente un return int_result_SP;
, con un tipo di reso dichiarato di EidosValue_SP, e che ha funzionato bene - il compilatore è felice di considerare EidosValue_Int_vector_SP come EidosValue_SP in quel contesto - ma io posso Lo facciamo qui a causa della logica condivisa nella parte inferiore della funzione.
Sono un po 'limitato nella mia implementazione qui perché questo codice è un collo di bottiglia e ha bisogno di correre veloce (e sì, so che da effettivamente strumentare il codice, e sì, conta davvero). Quindi è essenziale usare make_shared
per evitare una doppia allocazione, e vorrei anche fortemente evitare un incremento/decremento del conteggio quando porto il puntatore da int_result_SP
al risultato; Non voglio che ci sia un momento nel tempo in cui ci sono due shared_ptr che puntano alla nuova istanza. Quindi swap()
sembra la strada più ovvia da fare; ma sono bloccato da questo errore del compilatore. Perché sta accadendo e come posso risolverlo? Grazie!
APPENDICE:
Oh, riflettendo questo ulteriore Scommetto che so il motivo per cui l'errore sta accadendo. swap()
non ha obiezioni a mettere il EidosValue_Int_vector
nel EidosValue_SP
, ma è avere un problema con mettere il EidosValue
nel EidosValue_Int_vector_SP
; in quella direzione i tipi non sono compatibili. Non ci avevo pensato in questo modo poiché result
non ha alcun valore (ad esempio, è nullptr
, credo); ma ovviamente lo swap()
non lo sa. OK, quindi se questo è il problema, la domanda rimane: come posso effettuare il trasferimento mantenendo il codice velocemente - non facendo un conto inc/dec e non allontanandomi dall'uso di make_shared
?Ora che ho capito il problema (credo) sembra probabile che ci sia solo alcune API o trucco che ho trascurato ...
Sì, l'ho capito subito dopo aver cliccato. Vedi l'addendum che ho appena pubblicato. La domanda rimane come far funzionare il mio codice. – bhaller
just 'result = int_result_SP;'. Non è necessario lo swap – qehgt
"mantenendo il codice veloce" - cosa ti fa pensare che l'assegnazione stia rendendo il tuo codice ** non ** veloce? – YePhIcK