Wpis z mikrobloga

#programowanie #cpp
Dlaczego unique_ptr może być zwrócony przez funkcję przez wartość, skoro standard mówi, że zostaje on zniszczony podczas opuszczania zakresu ważności?
  • 14
  • Odpowiedz
  • Otrzymuj powiadomienia
    o nowych komentarzach

@Gladoo:12.8 §34, §35:

When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object [...] This elision of copy/move operations, called copy elision, is permitted [...] in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object with the same cv-unqualified type as the function return type [...]

When the criteria
  • Odpowiedz
W wielkim skrócie unique_ptr opuszcza scope ale z racji tego, że zwracasz go przez wartość zachodzi copy-ellision i zostaje on przesunięty do nowego zakresu bez niszczenia tego co jest pod wskaźnikiem.
  • Odpowiedz
@Malkof: Dlatego napisałem w wielkim skrócie. Szczegóły tego jak to dokładnie wygląda są w mojej pierwszej odpowiedzi a skoro pytanie pojawiło się w takiej formie w jakiej się pojawiło to copy-ellision raczej zaszło ;)
  • Odpowiedz
@Malkof: Owszem, nie musiało bo "an implementation is allowed to omit the copy/move construction". Plus (N)RVO jest w pewnych przypadkach (ot chociażby tak jak prawdopodobnie ten opa) gwarantowane od C++17 dlatego też tłumaczenie, że obiekt mógł zostać potraktowany jako r-value nie przekonuje mnie.
  • Odpowiedz
No ale zasadniczo co w związku z tym? Jak wrzucisz -fno-elide-constructors to dostaniesz explicite call move constructora. Jeśli wejdzie NRVO to tak jakby go nie było bo nie będzie takiej potrzeby.

Edit: O tutaj: https://en.cppreference.com/w/cpp/language/copy_elision

even if the copy/move constructor and the destructor have observable side-effects. The objects are constructed directly into the storage where they would otherwise be copied/moved to.


Więc jeśli wchodzi RVO to nie ma w ogóle mowy o
  • Odpowiedz
@Gladoo: Odpowiedzi o RVO i copy ellision są mylące bo pytasz o coś zupełnie innego. Podczas zwracania std::unique_ptr z funkcji jest on niszczony jak słusznie zauważasz, ale zanim zostanie zniszczony to zostaje wywołany move constructor i zasób na stercie jest przekazywany temu pointerowi do którego zwracasz z tej funkcji, a oryginalny po tej opracji zostaje wyczyszczony. I to potem ten pusty uniqueptr zostaje zniszczony przez wywołanie destruktora.
  • Odpowiedz
@Gladoo: Ogarnij sobie taki przykład: https://godbolt.org/z/crrYbqdxb

Tutaj jako "ładunek" masz int zamiast pamieci na stercie która miałbys w przypadku smart pointera ale ta zasada jest ta sama.

W srodku funkcji stwarzasz Cecylie z ladunkiem 3 i zwracasz ja do Aliny. Najpierw ladunek zostaje przeniesiony a potem pusta Cecylia jest niszczona. Na podobnej zasadzie dziala zwracania z unique_ptr

Patrz tylko na funkcje main() i f()
  • Odpowiedz