#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?
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 [...]
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.
@Gladoo: @Kermit96: Nie jest to do końca prawda, przecież nie zawsze mamy copy elision. Jest jeszcze jedna możliwość, obiekty, które opuszczają scope są traktowane jako r-value, czyli std::move jest wykonywany implicit.
@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 ;)
@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.
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.
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.
@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.
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
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?
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 for
Nie wiem po co to gdybanie. Czyli jak dodam flagę -fno-elide-constructors, która wyłącza NRVO to nie będzie się dało zwrócić unique_ptr?
Edit: O tutaj: https://en.cppreference.com/w/cpp/language/copy_elision
Więc jeśli wchodzi RVO to nie ma w ogóle mowy o
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.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()
if()