Wpis z mikrobloga

#cpp #programowanie

Mirki, żaden ze mnie ekspert w tej dziedzinie i dlatego postanowiłem aż się o to zapytać. Chodzi mi o funkcję std::move(). Ja rozumiem po co nam są move konstruktory, żeby nie kopiować obiektów tymczasowych a ukraść im bebechy i oszczędzić programowi roboty, szczytny cel.

Ale może mi ktoś podać jeden dobry przykład, kiedy ktoś zdrowy w ciele i umyśle chciałby użyć std::move()? Bo ta funkcja rozkazuje traktować lvalue jako rvalue (z tego co zrozumiałem z tłumaczeń gościa na yt, bo aż oglądam tutki myśląc, że chyba czegoś nie rozumiem, skoro działanie nosi znamiona bezsensu), czyli "udawaj, że jesteś tymczasowy na potrzeby move konstruktora". Efekt jest taki, że w jak mamy stary vector o nazwie "dupa" i zrobimy std::vector dupa2 (std::move(dupa)); to mówiąc krótko zmienimy nazwę z dupa na dupa2 i jeszcze w gratisie uzyskamy pusty vector o starej nazwie, którego użycie prawdopodobnie wysypie nam program.

Albo gość nie powiedział wszystkiego, albo ja po prostu nie mam pojęcia czemu miałbym tego używać tworząc chaos i problemy.
  • 12
  • Odpowiedz
@Viters: Już to czytałem, ale to sprawdza się generalnie do tego co mówiłem. Uzyskujemy zmianę nazwy obiektu i dostajemy invalida pod starą nazwą. Why?
  • Odpowiedz
@Khaine: Przenoszenie może tylko skopiować jakiś wewnętrzny address, zamiast całej zawartości. Przykładowo weź sobie taki unique_ptr: nie możesz go skopiować bo ma być unikalny, ale możesz go przenieść. Przykładowo możesz zrobić std::swap z pustym obiektem, z tego triku korzystało sporo bibliotek C++03. Niestety w przypadku przekazywania parametrów, nie da się tego wykorzystać bo wartość tymczasowa (rvalue) przekazuje się jako const& czyli swapa nie zrobisz. Dlatego powstał osobny typ rvalue,
  • Odpowiedz
@lionbest: Tak, ale tutaj mówimy o move konstruktorach i używaniu podwójnej referencji. A mnie chodzi o std::move(). Idea move konstruktorów i przeciążania na && jest bardzo fajna i oszczędna, tutaj wszystko się zgadzam.
  • Odpowiedz
@Khaine: Nom to jest dokładnie to samo. Można powiedzieć kiedy ma być kopia a kiedy przenoszenie.
Z std::move korzysta się sporadycznie, on tak naprawdę nic nie robi jedynie casta referencji. Destruktor tak czy siak się wywoła. Już częściej chyba std::forward się korzysta.
  • Odpowiedz
@Khaine:
class Foo
{
std::string name;
public:
Foo(std::string name) : name
(std::move(name)) {}
}

vs

class Foo
{
std::string name;
public:
Foo(const std::string& name) : name
(name) {}
}

Drugi przypadek i tak zawsze wykona kopie stringa w liscie inicjalizacyjnej. Pierwszy jest uzależniony od tego jak wywołasz konstruktor (może nie być kopii, jeśli argument wychodzi ze scopu, albo jest również przenoszony std::move)
  • Odpowiedz
@lionbest: Cały czas wyraźnie podkreślam, że wiem, że to nie to samo przecież ( ͡º ͜ʖ͡º) Konstruktor na rvalue jest bardzo sprytny i przyjemny. W klasach szablonowych robi już i tak za nas.
  • Odpowiedz