Jak przekazać inteligentne wskaźniki do funkcji?
Czy podczas przekazywania obiektów do funkcji, te same zasady mają zastosowanie do inteligentnych wskaźników, co do innych obiektów zawierających pamięć dynamiczną?
Kiedy przekazuję na przykład std::vector<std::string>
do funkcji zawsze rozważam następujące opcje:
-
Zamierzam zmienić stan obiektu wektorowego, ale nie chcę, aby zmiany te odzwierciedlały się po zakończeniu funkcji, czyli zrobić kopię.
void function(std::vector<std::string> vec);
-
Zamierzam zmienić stan wektora obiekt, a ja do chcę, aby zmiany te odzwierciedlały się po zakończeniu funkcji, aka wykonaj referencję.
void function(std::vector<std::string> & vec);
-
Ten obiekt jest dość duży, więc lepiej przekażę referencję, ale powiedz kompilatorowi, żeby nie pozwalał mi go zmieniać.
void function(std::vector<std::string> const& vec);
3 answers
Inteligentne Wskaźniki mają semantykę wskaźnika , nie semantykę wartości(cóż, nie tak, jak to masz na myśli). Pomyśl o shared_ptr<T>
jako o T*
; traktuj to jako takie (cóż, z wyjątkiem zliczania referencji i automatycznego usuwania). Kopiowanie inteligentnego wskaźnika nie kopiuje obiektu, do którego wskazuje, podobnie jak kopiowanie T*
nie kopiuje T
, do którego wskazuje.
W ogóle nie możesz skopiować unique_ptr
. Chodzi o to, że klasa nie może być skopiowana; gdyby mogła, to nie byłaby to unique (IE: singular) wskaźnik do obiektu. Musisz albo przekazać to przez jakąś formę odniesienia, albo przez przesuwając to.
Inteligentne Wskaźniki dotyczą własności tego, na co wskazują. Kto jest właścicielem tej pamięci i kto będzie odpowiedzialny za jej usunięcie. unique_ptr
reprezentuje unikalną własność: dokładnie jeden kawałek kodu posiada tę pamięć. Możesz przenieść własność (poprzez move
), ale w ten sposób, tracisz własność pamięci. shared_ptr
reprezentuje wspólne własność.
We wszystkich przypadkach użycie inteligentnego wskaźnika w liście parametrów reprezentuje przeniesienie własności. Dlatego, jeśli funkcja przyjmuje inteligentny wskaźnik, to rości sobie prawo własności do tego obiektu. Jeśli funkcja nie ma przejmować własności, to nie powinna w ogóle przejmować inteligentnego wskaźnika; użyj nagiego wskaźnika (T*
) lub referencji (T&
) i nie przechowuj go.
Jeśli mijasz kogoś a unique_ptr
, dajesz mu własność . Co oznacza, że z natury unikalnej własności, tracisz własność pamięci. Tak więc, nie ma prawie żadnego powodu, aby kiedykolwiek przekazać unique_ptr
przez cokolwiek, z wyjątkiem wartości.
Podobnie, jeśli chcesz podzielić się własnością jakiegoś obiektu, przekazujesz shared_ptr
. To, czy zrobisz to przez odniesienie, czy przez wartość, zależy od Ciebie. Ponieważ udostępniasz własność, i tak zrobi kopię (prawdopodobnie), więc równie dobrze możesz wziąć ją według wartości. Funkcja może używać std::move
do przenieś to na członków klasy lub tym podobne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-02 04:26:13
Jeśli funkcja nie zamierza modyfikować lub kopiować wskaźnika, po prostu użyj durnego wskaźnika. Inteligentne wskaźniki są używane do kontrolowania czasu życia obiektu, ale funkcja nie zmieni czasu życia, więc nie potrzebuje inteligentnego wskaźnika, a użycie głupiego wskaźnika daje pewną elastyczność w typie używanym przez wywołującego.
void function(std::string * ptr);
function(my_unique_ptr.get());
function(my_shared_ptr.get());
function(my_dumb_ptr);
unique_ptr
nie można go skopiować, więc jeśli musisz go przekazać, musisz przekazać referencję.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-20 20:14:34
Inteligentny wskaźnik to obiekt, który odnosi się do innego obiektu zarządzającego jego życiem.
W 1999 roku, po raz pierwszy w historii, po raz pierwszy w historii, po raz pierwszy w 1999 roku, po raz pierwszy w historii, po raz pierwszy w 1999 roku, po raz drugi w 1999 roku, po raz drugi w 1999 roku.]}- przechodzenie jako
const smartptr<T>&
zawsze działa (i nie można zmienić wskaźnika, ale można zmienić stan tego, co wskazuje). - przechodzenie jako
smartptr<T>&
zawsze działa (i można również zmienić wskaźnik). - Przejście jako
smartptr<T>
(przez kopiowanie) działa tylko wtedy, gdy smartptr jest kopiowalne. Informatyka działa zstd::shared_ptr
, ale nie zstd::unique_ptr
, chyba że "przesuniesz" go na wywołanie, jak wfunc(atd::move(myptr))
, tym samym anulującmyptr
, przesuwając wskaźnik do przekazanego parametru. (Zauważ, że ruch jest niejawny, Jeśli {[6] } jest tymczasowy). - podanie jako
smartptr<T>&&
(przez move) narzuca wskaźnik, który ma być przeniesiony podczas wywołania, zmuszając cię do jawnego użyciastd::move
(ale wymaga "move", aby mieć sens dla danego wskaźnika).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-02 03:56:22