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:

  1. 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);
    
  2. 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);
    
  3. 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);  
    
Czy to ta sama logika z inteligentnymi wskaźnikami? A kiedy powinienem rozważyć semantykę ruchu? Niektóre wytyczne dotyczące tego, jak powinienem przekazać inteligentne wskaźniki, są tym, czego najbardziej Pragnę.
Author: GManNickG, 2012-09-20

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.

 15
Author: Nicol Bolas,
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ę.

 4
Author: Mark Ransom,
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 z std::shared_ptr, ale nie z std::unique_ptr, chyba że "przesuniesz" go na wywołanie, jak w func(atd::move(myptr)), tym samym anulując myptr, 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życia std::move (ale wymaga "move", aby mieć sens dla danego wskaźnika).
 4
Author: Emilio Garavaglia,
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