Konstruktor klasy unique_ptr<T>
przyjmuje surowy wskaźnik do obiektu typu T
(a więc akceptuje a T*
).
W pierwszym przykładzie:
unique_ptr<int> uptr (new int(3));
Wskaźnik jest wynikiem new
wyrażenia, podczas gdy w drugim przykładzie:
unique_ptr<double> uptr2 (pd);
Wskaźnik jest przechowywany w pd
zmiennej.
Koncepcyjnie nic się nie zmienia (konstruujesz a unique_ptr
z surowego wskaźnika), ale drugie podejście jest potencjalnie bardziej niebezpieczne, ponieważ pozwoliłoby ci na przykład:
unique_ptr<double> uptr2 (pd);
unique_ptr<double> uptr3 (pd);
W ten sposób posiadanie dwóch unikalnych wskaźników, które skutecznie hermetyzują ten sam obiekt (naruszając w ten sposób semantykę unikalnego wskaźnika).
Dlatego pierwsza forma tworzenia unikalnego wskaźnika jest lepsza, jeśli to możliwe. Zauważ, że w C ++ 14 będziemy mogli:
unique_ptr<int> p = make_unique<int>(42);
Co jest zarówno jaśniejsze, jak i bezpieczniejsze. A jeśli chodzi o tę twoją wątpliwość:
Nie jest też dla mnie jasne, jak wskaźniki deklarowane w ten sposób będą się różniły od wskaźników deklarowanych w „normalny” sposób.
Inteligentne wskaźniki mają modelować własność obiektu i automatycznie dbać o zniszczenie wskazanego obiektu, gdy ostatni (inteligentny, posiadający) wskaźnik do tego obiektu znajdzie się poza zakresem.
W ten sposób nie musisz pamiętać wykonywania czynności delete
na obiektach alokowanych dynamicznie - destruktor inteligentnego wskaźnika zrobi to za Ciebie - ani martwić się, czy nie wyłuskujesz (wiszącego) wskaźnika do obiektu, który został już zniszczony:
{
unique_ptr<int> p = make_unique<int>(42);
}
Now unique_ptr
jest inteligentnym wskaźnikiem, który modeluje unikalną własność, co oznacza, że w dowolnym momencie w programie będzie tylko jeden wskaźnik (będący właścicielem) wskazanego obiektu - dlatego unique_ptr
nie można go skopiować.
Dopóki używasz inteligentnych wskaźników w sposób, który nie narusza niejawnej umowy, której wymagają od ciebie, będziesz mieć gwarancję, że żadna pamięć nie zostanie ujawniona, a odpowiednia polityka własności dla twojego obiektu będzie egzekwowana. Surowe wskazówki nie dają takiej gwarancji.
new int(3)
zwraca wskaźnik do nowegoint
, tak jakpd
wskaźnik do nowegodouble
.