Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Dlaczego konstruktor przenoszący nie może przyjmowac referencji do l-wartości

Ostatnio zmodyfikowano 2018-01-06 15:16
Autor Wiadomość
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.
C/C++
kontener( kontener && zrodlo )
    : T( zrodlo.T )
     , n( zrodlo.n ) // konstruktor przenoszący
{
    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.
P-168304
pekfos
» 2017-12-31 20:06:50
Niech ci będzie:
C/C++
#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.
P-168306
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').
P-168307
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').
C/C++
a = b;
Te równanie ma dwie lewe strony!
P-168308
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ść?
P-168309
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:
C/C++
#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>'
P-168310
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() .
C/C++
#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 ) ); //przenoszący
    A c( b ); //kopiujący
    A d;
    d = func(); //komplator sam wybiera operator przenoszący(obiekt tymczasowy)
    d = std::move( c ); //wymuszamy operator przenoszący
}



 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
P-168312
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:
C/C++
struct foo {
};

foo f();

void g()
{
    f() = foo { };
}
P-168319
« 1 » 2
  Strona 1 z 2 Następna strona