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

Deklarowanie zmiennych - w pętli czy poza nią

Object Storage Arubacloud
0 głosów
1,115 wizyt
pytanie zadane 1 stycznia 2020 w C i C++ przez Adrian234 Nowicjusz (120 p.)

Zdaję sobie sprawę, że zmienne zadeklarowane w pętli są widoczne tylko w niej. Mam pytanie odnośnie co jest lepszą praktyką.

Bazując na poniższym przykładzie:

W pierwszym przypadku zmienne są tworzone przed pętlami, co powoduje, że nie są deklarowane za każdym "okrążeniem" pętli, ale na początku kodu powstaje powoli mało przejrzyste "wysypisko" zmiennych.

W drugim przypadku deklaracje są umieszczone przed ich pierwszym użyciem, ale za każdym "okrążeniem" pętli znowu są deklarowane.

Zawsze używałem pierwszego rozwiązania(nie pamiętam już nawet powodu czemu tak robiłem). Jednak ostatnio robiłem program, w którym użyłem wiele zmiennych. Wypisanie ich wszystkich na samym początku wydaje mi się strasznie nie przejrzyste, więc zacząłem się zastanawiać czy dobrze robię.

 

#include <iostream>
#include <cstdlib>

using namespace std;

int main()
{

    int wybor;
    bool kontrola_bledow;
    string zmienna;

    while(true) {



       do  {
           kontrola_bledow=0;
           cout << endl << "Menu" << endl;
           cout << "1. Opcja 1" << endl;
           cout << "2. Opcja 2" << endl;
           cout << "3. Wyjscie" << endl;

           cout << "Wybieram:";
           cin >> wybor;

           switch(wybor) {

           case 1:
                // Jakis kod //
                kontrola_bledow=0;
                break;
           case 2:
                // Jakis kod //
                kontrola_bledow=0;
                break;
           case 3:
                exit(0);
           default:
                cout << "Podano zla wartosc!" << endl;
                kontrola_bledow=1;
           }


       }while(kontrola_bledow);

       cout << "Wpisz cos:";
       cin >> zmienna;

       cout << "Wpisales: " << zmienna;

    }

    return 0;
}

Czy

 

#include <iostream>
#include <cstdlib>

using namespace std;

int main()
{

    while(true) {

       bool kontrola_bledow;

       do  {
           kontrola_bledow=0;
           cout << endl << "Menu" << endl;
           cout << "1. Opcja 1" << endl;
           cout << "2. Opcja 2" << endl;
           cout << "3. Wyjscie" << endl;

           cout << "Wybieram:";
           int wybor;
           cin >> wybor;

           switch(wybor) {

           case 1:
                // Jakis kod //
                kontrola_bledow=0;
                break;
           case 2:
                // Jakis kod //
                kontrola_bledow=0;
                break;
           case 3:
                exit(0);
           default:
                cout << "Podano zla wartosc!" << endl;
                kontrola_bledow=1;
           }


       }while(kontrola_bledow);

       cout << "Wpisz cos:";
       string zmienna;
       cin >> zmienna;

       cout << "Wpisales: " << zmienna;

    }

    return 0;
}

 

2 odpowiedzi

0 głosów
odpowiedź 1 stycznia 2020 przez tkz Nałogowiec (42,000 p.)

Porównajmy assemblera. Pierwsze w pętli, drugie poza nią.

main:
        push    rbp
        mov     rbp, rsp
 
        mov     DWORD PTR [rbp-4], 0
.L3:
        cmp     DWORD PTR [rbp-4], 4
        jg      .L2
        mov     DWORD PTR [rbp-8], 4
        add     DWORD PTR [rbp-4], 1
        jmp     .L3
.L2:
        mov     eax, 0
        pop     rbp
        ret
main:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-8], 4
        mov     DWORD PTR [rbp-4], 0
.L3:
        cmp     DWORD PTR [rbp-4], 4
        jg      .L2
 
        add     DWORD PTR [rbp-4], 1
        jmp     .L3
.L2:
        mov     eax, 0
        pop     rbp
        ret

Zmienna jest przydzielana raz, gdy wywoływana jest funkcja. W rzeczywistości z punktu widzenia alokacji jest (prawie) tym samym, co deklaracja zmiennej na początku funkcji. Jedyną różnicą jest zakres: zmiennej nie można używać poza pętlą. 

https://stackoverflow.com/questions/7959573/declaring-variables-inside-loops-good-practice-or-bad-practice

Tutaj masz wszystko, nie wiem co więcej byłoby można dodać do tego wpisu. 

komentarz 2 stycznia 2020 przez j23 Mędrzec (194,920 p.)
W przypadku POD-ów to tak wygląda, ale jeśli mowa o nie-POD-ach, czyli klasach z konstruktorami/destruktorami, to definicja wewnątrz pętli powoduje odpowiedni narzut w postaci wywołania ctora i dtora. I o tym warto pamiętać.
komentarz 2 stycznia 2020 przez tkz Nałogowiec (42,000 p.)
Owszem i ta informacja jest zawarta w linku.
komentarz 2 stycznia 2020 przez j23 Mędrzec (194,920 p.)
edycja 2 stycznia 2020 przez j23
Nie wiem, nie wczytywałem się w posty z SO (generalnie jestem przeciwnikiem wrzucania linków do innych forów; masz coś do napisania, napisz to własnymi słowami).
komentarz 2 stycznia 2020 przez mokrowski Mędrzec (155,460 p.)

... to definicja wewnątrz pętli powoduje odpowiedni narzut w postaci wywołania ctora i dtora. I o tym warto pamiętać.

I jak najbardziej zgoda. I często jest to potrzebne przy wszelkiego rodzaju "RAII'owych" obsługach (blokady, monitory itp...) w C++.

Ogólnie lepsze jest lokalizowanie potrzebnej zmiennej bliżej jej użycia. Zarzut że to tworzy nieporządek, wynika najczęściej ze złej modularyzacji (bo skąd tyle zmiennych w tej jednostce kodu?).

Jeśli narzut ctor/dtor jest istotny, cóż... tu już dłuższa dyskusja.. Czy załatwiać to semantyką przenoszenia, mutowalnością/nie-mutowalnością zmiennej czy może inaczej (w zależności od kontekstu) :-)

Czasem niestety (dla C) nie ma wyjścia jeśli projekt jest utrzymany np. w C90 (lub są obostrzenia z procesu wytwarzania). Wtedy trzeba deklarować zmienną przed użyciem (prosty przykład: kernel GNU/Linux).

0 głosów
odpowiedź 2 stycznia 2020 przez Patrycjerz Mędrzec (192,320 p.)
edycja 2 stycznia 2020 przez Patrycjerz

Na początek należy przedstawić dwa pojęcia: deklaracji i definicji.

Deklaracja polega na stworzeniu symbolu w kodzie źródłowym o pewnej widoczności. Może to być nazwa zmiennej, ale również funkcji, klasy itp. Jest ona potrzebna jedynie w trakcie budowania programu.

Definicja zaś, jak sama nazwa wskazuje, definiuje zawartość. Może to być definicja zmiennej, funkcji, klasy. W przypadku zmiennych alokowana jest wtedy również pamięć. Jeśli napiszemy

void funkcja() {
    int i;
}

to zadeklarujemy i zdefiniujemy jednocześnie zmienną `i`. Jeśli napiszemy

void funkcja() {
    extern int i;
}

to jedynie zadeklarujemy zmienną `i`. Nie będzie ona stworzona w pamięci.

Zmienne lokalne (czyli zadeklarowane w funkcji, bez słowa `static`) są alokowane na stosie, w trakcie wejścia programu do funkcji. Nie ma więc znaczenia, gdzie zdefiniujesz zmienną: w pętli czy poza nią. Wygenerowany kod maszynowy będzie identyczny.

Sytuacja nieco się komplikuje, gdy definiujesz obiekt klasy w pętli. W trakcie definiowania takiej zmiennej wywoływany jest konstruktor, a po wyjściu z zakresu zmiennej, destruktor. Możliwe, że kompilator odpowiednio optymalizuje kod, aby niepotrzebnie nie wywoływać tych funkcji (jeśli przyjmują identyczne wartości za każdym obiegiem), ale nie jestem tego pewien.

Podobne pytania

0 głosów
2 odpowiedzi 224 wizyt
pytanie zadane 8 marca 2022 w C i C++ przez Daaa22 Dyskutant (8,250 p.)
0 głosów
1 odpowiedź 205 wizyt
pytanie zadane 16 stycznia 2023 w C i C++ przez polandonion Mądrala (7,040 p.)
+1 głos
1 odpowiedź 161 wizyt
pytanie zadane 13 kwietnia 2022 w C i C++ przez Szanti 2.0 Nowicjusz (150 p.)

92,590 zapytań

141,439 odpowiedzi

319,697 komentarzy

61,974 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!

...