Hej,
Dlaczego w przypadku używania std::move nie tworzy się osobnych konstruktorów tak jak pokazano to w // 1 i w // 2 tylko zwyczajnie używa się przekazywania przez wartość?
Przypadek // 1 w którym przekazujemy zwykłe l-wartości jestem w stanie zrozumieć, wtedy po prostu konwertujemy f i l za pomocą std::move na r-wartości i wywołujemy odpowiednie konstruktory przenoszące odpowiadających im klas skoro mamy r-wartości (std::move dokonuje konwersji przekazanego mu argumentu na r-wartość żeby można było go przenieść).
Nie rozumiem natomiast tego czemu nie tworzymy analogicznej funkcji jak pokazano w // 2 przyjmującej referencje do r-wartości. Przecież przekazując przez wartość std::string("Andrzej") do konstruktora // 1 skoro mamy przekazywanie przez wartość a nie referencję to i tak dokonywana jest kopia tego obiektu. Konkretnie tworzona jest obiekt tymczasowy i to co jest w tym obiekcie jest przenoszone do firstname i lastname. Gdyby użyć referencji do r-wartości to nie byłoby tworzonego żadnego obiektu tymczasowego.
Drugie moje pytanie dotyczy czy dobrze rozumiem dlaczego w kodzie załączonym do tego pytania mamy na wyjściu , , 12. Według mnie wyjście jest takie ponieważ w przypadku std::string zostały przeniesione zasoby powiązane z obiektem natomiast age nie otrzymał przypadkowej wartości dlatego że w tym przypadku age nie jest obiektem zarządzanym. Semantyka przenoszenia ma sens jedynie w odniesieniu do zasobów alokowanych dynamicznie przez new i delete lub w podobny sposób, zarządzanych przez instancje klas. W przypadku zwykłych intów czy floatów nie mamy odpowiedzialności za zwolnienie obiektu. Przeniesienie polega na transferze odpowiedzialności za zwolnienie zasobu. Ddobrze to rozumiem?
Trzecie pytanie dotyczy tego czy referencje do r-wartości wewnętrznie też są implementowane jako wskaźniki tak jak zwykłe l-wartościowe referencje.
Dziękuję i pozdrawiam,
whiteman808
~ ❯ cat main.cpp ✘ INT 19:30:01
#include <iostream>
#include <string>
class person {
public:
person() : firstname{}, lastname{}, age{0} {}
person(std::string f, std::string l, int a) // 1
: firstname{std::move(f)}, lastname{std::move(l)}, age{a} {
std::cout << f << ", " << l << ", " << a << '\n';
}
person(std::string&& f, std::string&& l, int a) // 2
: firstname{std::move(f)}, lastname{std::move(l)}, age{a} {
std::cout << f << ", " << l << ", " << a << '\n';
}
person(const person& p) { // konstruktor kopiujący
firstname = p.firstname;
lastname = p.lastname;
age = p.age;
}
private:
std::string firstname;
std::string lastname;
int age;
};
int main() {
person p{"Jan", "Kowalski", 12};
return 0;
}
~ ❯ ./main 19:30:04
, , 12