PDA

Visualizza la versione completa : [C++]Move constructor di shared_ptr


lovesemiramide
16-12-2013, 17:30
Giochicchiando un po' con gli smart pointers mi sono imbattuto nel codice sottostante che mi ha sorpreso non poco.


#include <iostream>
#include <memory>
#include <utility>

using namespace std;

struct Foo
{
~Foo() { cout << "~Foo()\n"; }
void f() const { cout << "Foo:f()\n"; }
};

int main()
{
unique_ptr< Foo > un{ new Foo() };
{
shared_ptr< Foo> sh = move(un);

sh->f();
}

if(!un)
cout << "un is empty\n";

un->f();

return 0;
}


Questo codice produce come output:

Foo:f()
~Foo()
un is empty
Foo:f()

Ma mi aspettavo almeno UB. Qualcuno saprebbe darmi una spiegazione?

shodan
16-12-2013, 22:21
E' qualcosa al limite dell'UB. All'atto pratico alcuni compilatori (non so se tutti) permettono di invocare un metodo attraverso un puntatore non valido PURCHE' tale metodo non acceda a variabili membro (si presume che tale comportamento abbia a che fare con ralune ottimizzazioni).
Se vuoi un UB basta che la funzione f() di Foo acceda a un dato membro (ad es. un int data).


struct Foo
{
~Foo() { cout << "~Foo()\n"; }
void f() const { data = 0; cout << "Foo:f()\n"; } // BOOM!
int data;
};

lovesemiramide
16-12-2013, 22:49
Interessante. Grazie mille! :)

MItaly
16-12-2013, 23:21
Richiamare un metodo su un puntatore non valido sempre UB. Tuttavia, normalmente i metodi non virtuali vengono implementati come normali funzioni che ricevono this come parametro nascosto, e se il metodo non accede ai membri della classe normale che non si verifichino errori appariscenti. (in effetti, una delle possibili manifestazioni dell'UB "tutto sembra funzionare correttamente")

Loading