• 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ą

Aruba Cloud VPS - 50% taniej przez 3 miesiące!
0 głosów
1,370 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,020 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 (195,260 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,020 p.)
Owszem i ta informacja jest zawarta w linku.
komentarz 2 stycznia 2020 przez j23 Mędrzec (195,260 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 (156,480 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 272 wizyt
pytanie zadane 8 marca 2022 w C i C++ przez Daaa22 Dyskutant (8,250 p.)
0 głosów
1 odpowiedź 228 wizyt
pytanie zadane 16 stycznia 2023 w C i C++ przez polandonion Dyskutant (7,560 p.)
+1 głos
1 odpowiedź 290 wizyt
pytanie zadane 13 kwietnia 2022 w C i C++ przez Szanti 2.0 Nowicjusz (150 p.)

93,191 zapytań

142,205 odpowiedzi

322,040 komentarzy

62,518 pasjonatów

Advent of Code 2024

Top 15 użytkowników

  1. 2817p. - dia-Chann
  2. 2769p. - Łukasz Piwowar
  3. 2759p. - Łukasz Eckert
  4. 2738p. - CC PL
  5. 2704p. - Tomasz Bielak
  6. 2678p. - Łukasz Siedlecki
  7. 2666p. - rucin93
  8. 2485p. - Marcin Putra
  9. 2475p. - Adrian Wieprzkowicz
  10. 2426p. - Mikbac
  11. 2418p. - Michal Drewniak
  12. 2239p. - Michał Telesz
  13. 2156p. - Anonim 3619784
  14. 1733p. - rafalszastok
  15. 1628p. - Dominik Łempicki (kapitan)
Szczegóły i pełne wyniki

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

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...