logo

Unique_ptr w C++

std::unique_ptr to inteligentny wskaźnik wprowadzony w C++ 11. Automatycznie zarządza dynamicznie przydzielanymi zasobami na stercie. Inteligentne wskaźniki to po prostu opakowania wokół zwykłych starych wskaźników, które pomagają zapobiegać powszechnym błędom. Mianowicie zapomnienie o usunięciu wskaźnika i spowodowanie wycieku pamięci lub przypadkowe usunięcie wskaźnika dwukrotnie lub w niewłaściwy sposób. Można ich używać podobnie jak standardowych wskaźników. Automatyzują niektóre ręczne procesy, które powodują typowe błędy.

Warunki wstępne: Wskaźnik w C++ , Inteligentne wskaźniki w C++.



Składnia

unique_ptr<  A>ptr1 (nowe A )>

Tutaj,

Co się stanie, jeśli zostanie użyte unikatowe_ptr?

Kiedy piszemy Unique_ptr ptr1 (nowy A), pamięć jest przydzielana na stercie dla instancji typu danych A. ptr1 jest inicjowany i wskazuje na nowo utworzony obiekt A. Tutaj ptr1 jest jedynym właścicielem nowo utworzonego obiektu A i zarządza życiem tego obiektu. Oznacza to, że gdy ptr1 zostanie zresetowany lub wyjdzie poza zakres, pamięć zostanie automatycznie zwolniona, a obiekt A zostanie zniszczony.

Kiedy używać Unique_ptr?

Gdy wymagana jest własność zasobu. Kiedy chcemy pojedynczej lub wyłącznej własności zasobu, powinniśmy sięgnąć po unikalne wskaźniki. Tylko jeden unikalny wskaźnik może wskazywać na jeden zasób. Zatem jednego unikalnego wskaźnika nie można skopiować do innego. Ułatwia także automatyczne czyszczenie, gdy dynamicznie przydzielane obiekty wychodzą poza zakres i pomaga zapobiegać wyciekom pamięci.



Uwaga: Musimy użyć nagłówkowy do korzystania z tych inteligentnych wskaźników.

Przykłady Unique_ptr

Przykład 1:

Stwórzmy strukturę A, która będzie miała metodę o nazwie printA wyświetlającą tekst. Następnie w sekcji głównej utwórzmy unikalny wskaźnik, który będzie wskazywał strukturę A. W tym momencie mamy instancję struktury A i p1 przechowuje wskaźnik na nią.

C++






// C++ Program to implement unique_ptr> #include> #include> using> namespace> std;> > struct> A {> >void> printA() { cout <<>'A struct....'> << endl; }> };> > int> main()> {> >unique_ptr p1(> new> A);> >p1->drukujA();> > >// displays address of the containing pointer> >cout << p1.get() << endl;> >return> 0;> }>

iteruj mapę Java

>

>

Wyjście

Java ma wartość zerową
A struct.... 0x18dac20>

Przykład 2

Stwórzmy teraz kolejny wskaźnik p2 i spróbujemy skopiować wskaźnik p1 za pomocą operatora przypisania (=).

C++




// C++ Program to implement unique_ptr> #include> #include> using> namespace> std;> > struct> A {> >void> printA() { cout <<>'A struct....'> << endl; }> };> int> main()> {> >unique_ptr p1(> new> A);> >p1->drukujA();> > >// displays address of the containing pointer> >cout << p1.get() << endl;> > >// will give compile time error> >unique_ptr> p2 = p1;> >p2->drukujA();> >return> 0;> }>

>

>

Wyjście

main.cpp: In function ‘int main()’: main.cpp:18:24: error: use of deleted function ‘std::unique_ptr::unique_ptr(const std::unique_ptr&) [with _Tp = A; _Dp = std::default_delete]’  18 | unique_ptr  p2 = p1;  | ^~ In file included from /usr/include/c++/11/memory:76,  from main.cpp:3: /usr/include/c++/11/bits/unique_ptr.h:468:7: note: declared here  468 | unique_ptr(const unique_ptr&) = delete;  | ^~~~~~~~~~>

Powyższy kod spowoduje błąd czasu kompilacji, ponieważ nie możemy przypisać wskaźnika p2 do p1 w przypadku unikalnych wskaźników. Musimy użyć semantyki ruchu w takim celu, jak pokazano poniżej.

xor kpp

Przykład 3

Zarządzanie obiektem typu A przy użyciu semantyki przenoszenia.

C++




// C++ Program to implement unique_ptr> #include> #include> using> namespace> std;> > struct> A {> >void> printA() { cout <<>'A struct....'> << endl; }> };> int> main()> {> >unique_ptr p1(> new> A);> >p1->drukujA();> > >// displays address of the containing pointer> >cout << p1.get() << endl;> > >// now address stored in p1 shpould get copied to p2> >unique_ptr> p2 = move(p1);> > >p2->drukujA();> >cout << p1.get() << endl;> >cout << p2.get() << endl;> >return> 0;> }>

>

>

Wyjście

A struct.... 0x2018c20 A struct.... 0 0x2018c20>

Należy zauważyć, że gdy adres ze wskaźnika p1 zostanie skopiowany do wskaźnika p2, adres wskaźnika p1 stanie się NULL(0) i adres przechowywany przez p2 będzie teraz taki sam jak adres przechowywany przez p1, co oznacza, że ​​adres w p1 został przesłany do wskaźnika p2 przy użyciu semantyki przenoszenia.