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

Operatory pre i post inkrmentacji

Aruba Cloud PRO i VPS, Openstack, VMWare, MS Hyper-V
+1 głos
430 wizyt
pytanie zadane 2 lutego 2017 w C i C++ przez Dexterim Dyskutant (8,370 p.)

Dlaczego to działa tak :)

 

#include <iostream>

int& fun(int &i){
return ++i;
}

int main(){

//…
int a=3, b=3;

std::cout<<a<< " " <<b; //3 3
a=fun(a)++;
std::cout<<a; //4

}

Zastanawiam się czemu a jest równe 4 a nie 5, ktoś umie wytłumaczyć

1 odpowiedź

+1 głos
odpowiedź 2 lutego 2017 przez criss Mędrzec (172,640 p.)
wybrane 2 lutego 2017 przez Dexterim
 
Najlepsza

Bo operator post-inkrementacji zwraca nowego inta o pierwotnej wartości inkrementowanego inta. A operator pre-inkrementacji zwraca referencje na inkrementowaną zmienną.

Na przykładzie kodu:

Weźmy sobie taką strukture. C++ nie pozwala na nadpisywanie operatorów typów wbudowanych, więc ciężko byłoby to sensownie pokazać.

struct Int
{
   int val;
   Int operator++(int); // operator post-inkrementacji
   Int & operator++(); // operator pre-inkrementacji
};

Int Int::operator++(int) //operator post-inkrementacji
{
   Int tmp = *this;
   this->val = this->val + 1;
   return tmp;
}

Int & Int::operator++() //operator pre-inkrementacji
{
   this->val = this->val + 1;
   return *this;
}

Dla rozróżnienia operator post-inkrementacji ma w argumencie symbolicznego inta. Stąd ten int w moim przykładzie.

komentarz 2 lutego 2017 przez Dexterim Dyskutant (8,370 p.)
Okej myślę, że zrozumiałem dzięki ;)
komentarz 2 lutego 2017 przez unknown Nałogowiec (39,620 p.)

Przecież ta linijka:

a=fun(a)++;

sprawia, że kod ma UB

komentarz 2 lutego 2017 przez criss Mędrzec (172,640 p.)
Dlaczego?
komentarz 2 lutego 2017 przez criss Mędrzec (172,640 p.)

Jeszcze dodatkowe wytłumaczenie dla ciebie @Dexterim, bo sam się zamotałem przez chwile jak teraz jeszcze raz spojrzałem.

fun(a)++; faktycznie zwiększa a do wartości 5, ale ostatecznie masz przypisanie a=fun(a)++; więc przypisujesz do a jej własną wartość z przed inkrementacji (bo to post-inkrementacja). Stąd wartość 4 na końcu.

komentarz 2 lutego 2017 przez unknown Nałogowiec (39,620 p.)

Drugi UB związany jest z post-inkrementacją i potencjalnie trywialną linijką a = a++. Jak się okazuje, są tutaj również dwie opcje, które rozważę posługując się kodem pomocniczym w postaci int a = 5; a = a++;.

Terminologia: 
a_mem - a w pamięci (np. jako lokalna zmienna na stosie)
a_copy - kopia a w jakimś podręcznym rejestrze

Opcja 1. Wynikowy kod ma następującą formę (w pseudo-assembly):
Warunki początkowe: (a_mem == 5, a_copy == brak)

Krop 1. Podstawienie a do równania.
a = 5++; (a_mem == 5, a_copy == 5)

Krok 2. Post-inkrementacja na zmiennej w pamięci.
a = 5;   (a_mem == 6, a_copy == 5)

Krok 3. Przypisanie, czyli a_copy leci do a_mem.
(a_mem == 5, a_copy == brak)
W powyższym wypadku wynik post-inkrementacji a zaginął w akcji. Tj. niby zostało zapisane do pamięci, ale po chwili operacja przypisania (=) wrzuciła finalny wynik obliczeń (czyli 5) do zmiennej a w pamięci nadpisując jednocześnie wynik post-inkrementacji. (prawdę mówiąc zawsze uważałem, że operacja post-inkrementacji jest deferowana na sam koniec wszystkich obliczeń, więc uznałbym to zachowanie za bug kompilatora)

Opcja 2. Post-inkrementacja dzieje się po przypisaniu.
Warunki początkowe: (a_mem == 5, a_copy == brak)

Krop 1. Podstawienie a do równania.
a = 5++; (a_mem == 5, a_copy == 5)

Krok 3. Przypisanie, czyli a_copy leci do a_mem.
(zostaje a++) (a_mem == 5, a_copy == brak)

Krok 2. Post-inkrementacja na zmiennej w pamięci.
(a_mem == 6, a_copy == brak)

Czyli post-inkrementacja zostaje faktycznie zdeferowana na koniec obliczeń.

Źródło: http://gynvael.coldwind.pl/?id=369

komentarz 2 lutego 2017 przez unknown Nałogowiec (39,620 p.)
W GCC zmienna a ma wartość 4 a VS 5
komentarz 2 lutego 2017 przez Dexterim Dyskutant (8,370 p.)
Wiem jak to działa tylko na początku referncja zwracana mnie zmyliła @Criss
komentarz 2 lutego 2017 przez criss Mędrzec (172,640 p.)
Hm, no dobra, to dzięki @unknown za poprawienie.

W takim razie moje wytłumaczenie operatorów ++() i ++(int) może pozostać, ale w tej konkretnej sytuacji niczego nie wyjaśnia.

Podobne pytania

0 głosów
1 odpowiedź 420 wizyt
pytanie zadane 11 listopada 2016 w SQL, bazy danych przez kistel66 Początkujący (370 p.)
0 głosów
1 odpowiedź 458 wizyt
0 głosów
1 odpowiedź 118 wizyt
pytanie zadane 9 grudnia 2015 w C i C++ przez PoProstuTomasz Początkujący (470 p.)

90,816 zapytań

139,494 odpowiedzi

313,557 komentarzy

60,313 pasjonatów

Motyw:

Akcja Pajacyk

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

Sklep oferujący ćwiczenia JavaScript, PHP, rozmowy rekrutacyjne dla programistów i inne materiały

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...