I seguenti programma va in crash con un cattivo glibc doppia errori:Cosa succede se reimpostare uno std :: shared_ptr a se stesso
#include <iostream>
#include <memory>
class foo {
public:
foo()
{
std::cout << "foo constructed" << std::endl;
}
~foo()
{
std::cout << "foo destructed" << std::endl;
}
};
int main() {
auto f = std::make_shared<foo>();
std::cout << "Before reset" << std::endl;
f.reset(f.get());
std::cout << "After reset" << std::endl;
return 0;
}
Da questo ottengo il seguente output (seguita dall'errore di glibc):
foo constructed
Before reset
foo destructed
After reset
foo destructed
Quindi, ovviamente, in questo caso l'oggetto viene distrutto due volte. Una volta dal reset e una volta dallo std::shared_ptr
uscendo dal campo di applicazione. Questo è in realtà quello che mi sarei aspettato.
Su cppreference tuttavia trovo il seguente testo (che si trova a http://en.cppreference.com/w/cpp/memory/shared_ptr/reset):
If *this already owns an object and it is the last shared_ptr owning it, the object is destroyed through the owned deleter, unless ptr is a pointer to it.
A mio parere questo dice in realtà, che l'oggetto non deve essere distrutta come nel mio esempio. Abbastanza sorprendente, ma se lo standard lo dice. Sono in qualche modo frainteso questo, oppure l'implementazione di std::shared_ptr
non è conforme allo standard?
Per coloro che chiedono il motivo per cui sto facendo questo:
Attualmente sto cercando di capire come gestire temporaneamente puntatori nude per oggetti creati da new
e new[]
. L'idea è di usare lo std::shared_ptr::reset()
per sostituire il deleter con un deleter no-op. L'alternativa è di avvolgere il codice con un tipo di blocco try { stuff() } catch(...) { delete x; throw;}
.
'f.reset (f.get())' perché dovresti mai * * vuoi fare questo? Se hai "puntatori nudi agli oggetti" temporanei, non dovresti * cancellarli *. Dovresti eliminare solo ciò che * possiedi * e non possiedi ciò che ottieni da 'shared_ptr :: get'. –
@NicolBolas: Risposta facile: poiché cppreference ha suggerito che questo sarebbe stato gestito in modo diverso rispetto ad altri casi. Sembra che l'informazione sia sbagliata. Inizierò una discussione su questo in cppreference. – LiKao
Questo spiega solo perché hai pensato che avrebbe funzionato. Questo non spiega perché hai pensato che sarebbe stata una buona idea, che funzioni o meno. Cosa stai cercando di fare * per * questo * questo? –