latajacaryba Temat założony przez niniejszego użytkownika |
Dlaczego konstruktor przenoszący nie może przyjmowac referencji do l-wartości » 2017-12-31 19:33:38 Witam. Nie rozumiem sensu użycia r-referencji przy konstruktorach przenoszących. W https://kacperkolodziej.pl/programowanie/cpp11-referencje-do-r-wartosci-i-przenoszenie-danych.html artykule i do niego będę się do niego odnosił, jest napisane, że: "służą do nadawania nazw obiektom tymczasowym, które swojej nazwy nie posiadają, więc nie mogą posiadać normalnej referencji." No i są wykorzystywane przy wspomnianych konstruktorach przenoszenia. Tylko przecież taki konstruktor można uzyskać wykorzystując referencję do l-wartości. kontener( kontener && zrodlo ) : T( zrodlo.T ) , n( zrodlo.n ) { std::cout << "konstruktor przenoszacy z " << reinterpret_cast < const void *>( & zrodlo ) << " do " << reinterpret_cast < const void *>( this ) << "\n"; zrodlo.T = nullptr; }
Można by równie dobrze użyć "zwykłej referencji". Po co więc ona tu jest? EDIT: poprawiona literówka w tytule tematu. |
|
pekfos |
» 2017-12-31 20:06:50 Niech ci będzie: #include <iostream>
struct A { A() = default; A( const A & ) { std::cout << "const&\n"; } A( A & ) { std::cout << "&\n"; } void f() { } };
int main() { A a; A b { a }; a.f(), b.f(); } W oczywisty sposób chcę obiekt skopiować (później są użyte oba obiekty), ale zostaje wywołany konstruktor 'przenoszący'. Musiałbym tu używać const_cast, żeby chronić obiekt przed zniszczeniem. |
|
latajacaryba Temat założony przez niniejszego użytkownika |
» 2017-12-31 21:11:30 czyli z tego co rozumiem, jest to po to, żeby odróżnić konstruktor przenoszenia od kopiowania? Tylko jeszcze jak ma tu sie r-referencja? Ma ona być referencją na r wartości, czyli te po drugiej stronie znaku równości, a tymczasem przekazujemy przez tą referencje obiekt, który przecież jest l wartością (w twoim przypadku 'a'). |
|
pekfos |
» 2017-12-31 22:29:54 Ma ona być referencją na r wartości, czyli te po drugiej stronie znaku równości, a tymczasem przekazujemy przez tą referencje obiekt, który przecież jest l wartością (w twoim przypadku 'a'). |
Te równanie ma dwie lewe strony! |
|
latajacaryba Temat założony przez niniejszego użytkownika |
» 2017-12-31 23:09:35 No to obie wartości są l-wartościami. Dlaczego więc przenoszący operator przypisania ma r-referencję skoro przekazujemy l-wartość? |
|
Elaine |
» 2017-12-31 23:18:40 Tylko przecież taki konstruktor można uzyskać wykorzystując referencję do l-wartości. |
Nie można, zmienna referencja do lwartości nie może odnosić się do rwartości: #include <vector>
std::vector < int > foo(); void bar( std::vector < int >& x );
void qux() { bar( foo() ); }
error: cannot bind non-const lvalue reference of type 'std::vector<int>&' to an rvalue of type 'std::vector<int>'
|
|
mateczek |
» 2017-12-31 23:49:04 Operatory przenoszące używasz gdy chcesz zniszczyć źródło . Stosujesz do zmiennych tymczasowych . Możesz wymusić stosowanie operatora (konstruktora) do normalnych obiektów korzystając z std::move() . #include <iostream> using namespace std; class A { public: A() { } A( A && ) { cout << "konstruktor przenoszący" << endl; } A( const A & ) { cout << "konstruktor kopiujący" << endl; } void operator =( A && ) { cout << "operator przypisania przenoszący" << endl; } }; A func() { A temp; return temp; } int main() { A a; A b( std::move( a ) ); A c( b ); A d; d = func(); d = std::move( c ); }
r wartości, czyli te po drugiej stronie znaku równośc
|
r wartości, oznacza obiekt, do którego nie można nic przypisać!!! A jedynie on sam może być przypisany (obiekt może stać tylko po prawej stronie znaku "=") Są to miedzy innymi zmienne tymczasowe zwracane przez funkcje |
|
Elaine |
» 2018-01-01 02:01:16 r wartości, oznacza obiekt, do którego nie można nic przypisać!!! A jedynie on sam może być przypisany (obiekt może stać tylko po prawej stronie znaku "=") |
Nazwy rwartości (a także lwartości, xwartości, prwartości i glwartości) należy traktować jako co najwyżej historyczne ciekawostki. Wynik funkcji f jest tutaj prwartością, ale można do niego przypisać, bo jest typu klasowego, więc ma niejawnie zdefiniowany (tutaj trywialny) kopiujący operator przypisania bez kwalifikacji referencyjnej: struct foo { };
foo f();
void g() { f() = foo { }; }
|
|
« 1 » 2 |