• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Obiekty, zwracanie przez wartość - kilka pytań

Object Storage Arubacloud
+1 głos
261 wizyt
pytanie zadane 16 maja 2018 w C i C++ przez Jakub 0 Pasjonat (23,120 p.)
zamknięte 17 maja 2018 przez Jakub 0

Hej, niby zwracanie obiektów/zmiennych przez wartość do podstawy-podstaw jednak kiedy w książce była mowa o zwracaniu przez wartość obiektu niemodyfikowalnego (const) to sprawa się nawet rozwinęła i zadałem sobie wiele pytań...

np. taki programik:

class Kl{
public:
    int a;
    int b;

    Kl(int v){
        a=v;
        b=v*2;
    }
};

int r1(){ //zwraca int 
    int i = 6;
    return i;
}

Kl r2(){ //zwraca Kl
    Kl k = 4;
    return k;
}


int main(){
    r1() = 3; //to powoduje błąd 
    r2() = 3; //jest ok
}

Dlaczego użycie po lewej stronie wyrażenia funkcji zwracającej int'a powoduje błąd a w przypadku zwracającej nasz obiekt już nie? ( wiem oczywiście że z obiektem też byś my nie mogli tak zrobić zwracając go z użyciem const ). Jednym słowem dlaczego r1() zwraca nam r-wartość a r2() już chyba l-wartość ?

Zaciekawiła mnie jeszcze kwestia konstruktora kopiującego, gdy mam takie coś:

class Kl{
    Kl(const Kl& k){
        *this = k;
    }
public:
    int a;
    int b;

    Kl(int v){
        a=v;
        b=v*2;
    }
};

Przez to nie ma możliwości zwracania obiektu przez wartość bo nie ma publicznego konstruktora kopiującego, to rozumiem.

Zaciekawiło mnie jednak że w ogóle w ciele konstruktora możemy używać wskaźnika this ( na obiekt wywołujący ), skoro konstruktor dopiero tworzy ten obiekt, to formalnie tego obiektu jeszcze nie ma więc jak się możemy do niego odwoływać? No chyba że powstaje jeszcze przed wywołaniem takiego konstruktora, chyba na pewno bo teraz zanegowałem prawo działania jakiegokolwiek konstruktora ;).

I jeszcze jedno:
 

class Kl{
public:
    int a;
    int b;

    Kl(const Kl& k){ //mój konstruktor kopiujący 
        std::cout<<"(Kl)\n";
        *this = k;
    }

    Kl(int v){
        std::cout<<"(int)\n";
        a=v;
        b=v*2;
    }

    Kl operator=(int v){
         std::cout<<"(operator)\n";
        a=v;
        b=v*2;
    }

};

Kl r2(){
    Kl k = 4;
    return k;
}

W funkcji r2() przy zwracaniu obiektu konstruktor kopiujący powinien mi dać o sobie znać, a nie mam żadnego takiego powiadomienia jak (Kl). Dlaczego? To tak jakby kompilator i tak użył teraz wbudowanego konstruktora kopiującego :/ Z drugiej strony jak go przeniosę do składowych prywatnych to jest błąd. O co tu chodzi?

Z góry dziękuje wam za pomoc i serdecznie pozdrawiam.

komentarz zamknięcia: już znam wytłumaczenie

2 odpowiedzi

+1 głos
odpowiedź 16 maja 2018 przez RafalS VIP (122,820 p.)
wybrane 16 maja 2018 przez Jakub 0
 
Najlepsza
Można użyć this, bo w momencie wejścia do ciała konstruktora obiekt jest gotowy do używania. To tylko Twoje widzimisię że chcesz coś do stworzonych zmiennych przypisać.

Ostatnie to optymalizacja kompilatora. Poczytaj o copy elision. Jak nie znasz angielskiego to w skrocie kompilator czasem wykryje ze nie ma sensu mnożyć niepotrzebnych kopii i pominie jawne wywolanie konstr kopiującego.

Co do pierwszego obydwa zwracają rwartosc, ale drugie na prawdę wygląda tak: r2().ooperator=(3), w argumencie niejawna konwersja na Kl i to oczywiście powinno działać w przeciwienstwie do 5=3.
komentarz 16 maja 2018 przez Jakub 0 Pasjonat (23,120 p.)

Dziękuje, wszystko zrozumiałem, ale zastanawiam się jeszcze nad tym ( moim pierwszym pytaniem ):

obydwa zwracają rwartosc, ale drugie na prawdę wygląda tak: r2().ooperator=(3), w argumencie niejawna konwersja na Kl i to oczywiście powinno działać w przeciwienstwie do 5=3.

Tak najprościej mówiąc, dało by się po prostu powiedzieć że dla r-wartości naszego obiektu istnieje operator przypisania a dla typu int nie ma takiej możliwości? Bo chce to sobie jakoś logicznie ułożyć w głowie, z innej odpowiedzi widzę że dało by się operator '=' dla r-wartości wyłączyć stąd ten wniosek.

1
komentarz 16 maja 2018 przez RafalS VIP (122,820 p.)
Tak mozna tak o tym myslec. Jeśli klasa ma operator przypisania to działa to jak wywołanie metody na obiekcie tymczasowym. Gdy nie ma tego operatora to jest blad.
1
komentarz 16 maja 2018 przez RafalS VIP (122,820 p.)
Jesli szukasz zasady to nie wolno przypisać do rwartosci, ale mozna na niej wysolac metodę, przez co do klas przypisywalnych da sie przypisac mimo ze sa rwartosciami.
+1 głos
odpowiedź 16 maja 2018 przez j23 Mędrzec (194,920 p.)
edycja 16 maja 2018 przez j23

Jednym słowem dlaczego r1() zwraca nam r-wartość a r2() już chyba l-wartość ?

r2 zwraca r-wartość. Możesz sobie zrobić eksperyment: zdefiniuj operator przypisania dla obiektów, które są l-wartością, a zablokuj dla r-wartości:

    Kl& operator=(const Kl&) & { return *this; };
    Kl& operator=(const Kl&) && = delete;

  Zobaczysz, że linia r2() = 3; już nie jest ok, choć zwykłe przypisanie, Kl x; x = 3; będzie się kompilować.

komentarz 16 maja 2018 przez Jakub 0 Pasjonat (23,120 p.)
Wow, pierwszy raz widzę takie zapisy/metody ( nawet nie wiem jak to nazwać ) :/

Tak z ciekawości to występują one w c++11? Bo nie wiem czy będę mieć o tym w książce a na tym standardzie jest ona oparta.
komentarz 16 maja 2018 przez j23 Mędrzec (194,920 p.)
Tak, to występuje od C++11.

Podobne pytania

+1 głos
1 odpowiedź 302 wizyt
pytanie zadane 1 września 2017 w PHP przez KlejnotNilu Użytkownik (750 p.)
0 głosów
2 odpowiedzi 770 wizyt
pytanie zadane 14 października 2018 w C i C++ przez Vitall Początkujący (400 p.)
0 głosów
0 odpowiedzi 608 wizyt

92,576 zapytań

141,426 odpowiedzi

319,651 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...