2012-07-02 13 views
12

Próbowałem pisania tej klasyDziwne zachowanie dla unique_pointer w Visual Studio 2010

#include <memory> 

class ContainerUnique 
{ 
public: 

    ContainerUnique(void); 
    ~ContainerUnique(void); 

private: 
    std::unique_ptr<UniqueElement> u; 
}; 

Gdzie UniqueElement jest klasa POD zdefiniowane gdzie indziej. Teraz definiuję korpus konstruktora w następujący sposób:

ContainerUnique::ContainerUnique(void) 
{ 
    auto tmp = new UniqueElement(1); 

    this->u(tmp); // u is a unique_ptr<UniqueElement>. Should this call compile? 
} 

I spełnia wszystkie wymagania bez wyjątków. Uruchamianie programu Zauważyłem, że po wywołaniu konstruktora ContainerUnique, u zawiera zerowy wskaźnik.

Czy to jest zamierzone zachowanie? I do jakiej konkretnie metody wzywam?

+3

Nie jesteś pewien problemów, które napotykasz. Ale unikaj ich, inicjując zmienną składową u na liście initialaztrion konstruktora. –

+0

Tak, to jest rozwiązanie, którego użyłem w moim prawdziwym kodzie, ale nadal nie jestem pewien co dzieje się w tym przykładzie. –

+0

Spróbuj wydrukować typ swojej automatycznej zmiennej. Nie wiem, czy działa typid. Gdy znacie typ, reszta powinna być łatwa. –

Odpowiedz

19

This is a known problem with VS2010's unique_ptr.publicznie dziedziczy z jego Deleter jeśli jest to pusty jak optymalizacji (pusty optymalizacji bazowa). Minusem spadku publicznego jest to, że wszyscy członkowie deletera stają się również członkami unique_ptr, w tym przypadku jego operator()(T*), który usuwa wskaźnik.

Błąd został naprawiony w bibliotece VS2012, w której dziedziczenie zostało zmienione na prywatne.

+1

ah, pokonałeś mnie. Dobre znalezisko. – stijn

2

To powinno być zrobione jak

ContainerUnique::ContainerUnique(void):u(new UniqueElement(1)) { 
} 
+1

W ten sposób rozwiązałem problem w kodzie produkcyjnym, ale nadal nie jestem pewien, co dzieje się w tym przykładzie. –

8

Dzwonisz pod numer default_delete<UniqueElement>::operator() (UniqueElement* ptr), ponieważ wywodzi się z niego uniqe_ptr (aby skorzystać z pustej optymalizacji klasy bazowej) i usuwa ptr. To nie jest dokładnie zamierzone zachowanie, chociaż nie sądzę, żeby standard zabraniał tego.