Jak mogę zadeklarować i zdefiniować wiele zmiennych w jednym wierszu przy użyciu C ++?

173

Zawsze myślałem, że jeśli zadeklaruję te trzy zmienne, wszystkie będą miały wartość 0

int column, row, index = 0;

Ale uważam, że tylko indeks jest równy zero, a pozostałe to śmieci, takie jak 844553 i 2423445.

Jak mogę zainicjować wszystkie te zmienne na zero bez deklarowania każdej zmiennej w nowym wierszu?

Sam
źródło
36
Ostrożnie z tymi jednowierszowymi deklaracjami wielu zmiennych. Zadeklarowanie wskaźnika int, po którym następuje lista zwykłych liczb całkowitych ( int* a, b, c;nie robi tego, na co wygląda), jest łatwiejsze niż myślisz .
Chris Eberle,
4
Są tylko trzy zmienne, stary, napisz =0dla każdej z nich w ich definicjach. A jeśli naprawdę potrzebujesz wielu zmiennych, wypróbuj tablicę: int a[10]={0}zainicjuje każdą a[i]z nich na 0.
Stan
Kompilator nie powinien zezwalać na taką konstrukcję, jeśli ma zachowywać się inaczej niż by się spodziewał rozsądny programista ...
imho
1
@ cph2117 Rozsądny programista pomyślałby: „hmm, ta składnia może oznaczać kilka różnych rzeczy w zależności od tego, jak gramatyka wiąże rzeczy” , odszukałby Standard, aby dowiedzieć się, który jest prawdziwy, i zająć się nim.
underscore_d
Przestań to robić. To tylko sprawia, że ​​kod jest trudniejszy do odczytania. Celem pisania kodu w języku wysokiego poziomu jest ułatwienie jego czytania opiekunowi.
Martin York

Odpowiedzi:

202
int column = 0, row = 0, index = 0;
Josh
źródło
162

Kiedy deklarujesz:

int column, row, index = 0;

Tylko indeks jest ustawiony na zero.

Możesz jednak wykonać następujące czynności:

int column, row, index;
column = index = row = 0;

Ale osobiście wolę, co zostało wskazane.
Moim zdaniem jest to bardziej czytelna forma.

int column = 0, row = 0, index = 0;

lub

int column = 0;
int row = 0;
int index = 0;
Matt
źródło
3
Pomiędzy ostatnimi dwoma decyduję na podstawie tego, czy te dwie wartości muszą być naprawdę tego samego typu ( bool previousInputValue, presentInputValue;), czy po prostu są tego samego typu teraz, ale tak naprawdę nie muszą być ( uint8_t height, width;mogą zmienić się uint8_t height; uint16_t width;w w przyszłości i powinny być uint8_t height; uint8_t width;najpierw).
altendky
Ponieważ pisanie uint8_t height; uint16_t width;zamiast uint8_t height, width;oszczędza 10 znaków w przyszłości. :-) możesz to oczywiście zrobić, jak chcesz. Tylko upewnij się, że łatwo je odczytać. Więc ostatnia forma jest najbardziej wyraźna.
Matt,
Ostatnia forma jest z pewnością najbardziej jednoznaczna w określaniu typu każdej zmiennej i wyjaśnianiu, że każda z nich jest inicjalizowana. To powiedziawszy, nie jest jasne, czy kolumna i wiersz mają być tego samego typu, czy nie. Być może oboje wolelibyśmy jawność int presentValue = 0; typeof(presentValue) previousValue = presentValue;, ale uważam, że typeof()jest to niestandardowe rozszerzenie GCC.
altendky
49

Jak powiedział @Josh, prawidłowa odpowiedź to:

int column = 0,
    row = 0,
    index = 0;

Musisz uważać na to samo ze wskazówkami. To:

int* a, b, c;

Jest równa:

int *a;
int b;
int c;
Mateen Ulhaq
źródło
34
Nienawidzę tego wskaźnika, to nie ma sensu. Gwiazdka jest częścią typu, więc powinna dotyczyć ich wszystkich. Wyobraź sobie, że unsigned long x, y;zadeklarowane xjako unsigned longale yjak tylko unsigned, aka unsigned int! To jest dokładnie to samo! </rant>
Cam Jackson
6
To ma sens. "int * a, b, c;"
Jeroen,
7
@JeroenBollen Cóż, tak, ma sens, jeśli napiszesz gwiazdkę wskaźnika obok nazwy zmiennej zamiast jej typu, ale to samo w sobie nie ma żadnego sensu. Jak powiedziałem powyżej, gwiazdka jest częścią typu, a nie częścią nazwy, więc powinna być zgrupowana z typem!
Cam Jackson
11
Z drugiej strony nie, w rzeczywistości ma sens, że * niekoniecznie musi być częścią typu, ponieważ int *aoznacza, że *areprezentuje intwartość.
mdenton8
2
Chodzi już o to, ale samo dodanie do tego pustki jest zasadniczo brakiem typu, ale nadal można do niego wskazać. Więc dlaczego void* abędzie kompilować, a void *a, b, cnie. Ta racjonalizacja działa na mnie.
Josh C
25

Zadeklarowanie jednej zmiennej / obiektu w wierszu nie tylko rozwiązuje ten problem, ale także czyni kod bardziej przejrzystym i zapobiega głupim błędom podczas deklarowania wskaźników.

Aby jednak bezpośrednio odpowiedzieć na pytanie, musisz jawnie zainicjować każdą zmienną na 0. int a = 0, b = 0, c = 0;.

Mark B.
źródło
16
int column(0), row(0), index(0);

Zwróć uwagę, że ten formularz będzie działał również z typami niestandardowymi, zwłaszcza gdy ich konstruktory przyjmują więcej niż jeden argument.

Michael Kristofik
źródło
2
a obecnie z jednolitą inicjalizacją (w oczekiwaniu na C ++ 17 naprawienie tego dla auto...): int kolumna { 0 } , wiersz { 0 } , indeks { 0 } ;
underscore_d
5

Od 2k18 możesz korzystać z powiązań strukturalnych :

#include <iostream>
#include <tuple>

int main () 
{
    auto [hello, world] = std::make_tuple("Hello ", "world!");
    std::cout << hello << world << std::endl;
    return 0;
}

Demo

ivaigult
źródło
4

Możliwe podejścia:

  • Zainicjuj wszystkie zmienne lokalne zerem.
  • Miej tablicę memsetlub {0}tablicę.
  • Ustaw go jako globalny lub statyczny.
  • Umieść je structi / memsetlub miej konstruktora, który zainicjuje je do zera.
Ajay
źródło
# zdefiniować KOLUMNĘ 0 # zdefiniować WIERSZ 1 # zdefiniować INDEKS 2 # zdefiniować AR_SIZE 3 int Dane [ AR_SIZE ]; // Tylko pomysł.
Ajay
Przepraszam, chodziło mi o to, dlaczego w swojej odpowiedzi umieściłeś wiersz „ Masz tablicę, zestaw memów lub {0} tablicę ”?
Mateen Ulhaq
memset (Data, 0, sizeof (Data)); // Jeśli można to logicznie spakować.
Ajay
2

Nie polecałbym tego, ale jeśli naprawdę chcesz być jedną linijką i pisać 0 tylko raz, możesz również zrobić to:

int row, column, index = row = column = 0;
Levi Uzodike
źródło
0

Jak wspominali inni, począwszy od C ++ 17 można korzystać z powiązań strukturalnych do przypisywania wielu zmiennych.

Łącząc to z std::arrayi odliczenia szablon argumentu możemy napisać funkcję, która przypisuje wartość do dowolnej liczby zmiennych bez powtarzania typ lub wartość .

#include <iostream>
#include <array>

template <int N, typename T> auto assign(T value)
{
    std::array<T, N> out;
    out.fill(value);
    return out;
}

int main()
{
    auto [a, b, c] = assign<3>(1);

    for (const auto& v : {a, b, c})
    {
        std::cout << v << std::endl;
    }

    return 0;
}

Demo

jb
źródło
-13

Kiedy deklarujesz zmienną bez jej inicjalizacji, wybierana jest liczba losowa z pamięci i zmienna jest inicjalizowana do tej wartości.

user3487742
źródło
7
nie całkiem. Kompilator decyduje, że
``
3
@ pm100, chociaż lepsze i prawdziwe w przypadku każdej trywialnej implementacji, która nie wychodzi z siebie, by nękać użytkowników ... to wciąż zbytnie uproszczone ;-), ponieważ użycie niezainicjowanej zmiennej to UB, więc teoretycznie wszystko może się zdarzyć, w tym dowolny kod używanie tej zmiennej po prostu jest usuwane z programu - co jest szczególnie prawdopodobne, gdy w grę wchodzi optymalizacja.
underscore_d
1
wartością tej zmiennej będzie cokolwiek znajdowało się pod adresem, który otrzymała, tj. śmieci.
Pedro Vernetti,
@PedroVernetti Nie ma znaczenia, co stało się pod podanym adresem, zanim nowa zmienna została zadeklarowana i otrzymała ten sam adres. Jeśli użytkownik zadeklaruje nową zmienną bez inicjowania jej wartością, a następnie odczyta zmienną przed przypisaniem jej wartości, program zachowuje się niezdefiniowane. To nieskończenie gorsze niż „przypadkowe” i „śmieciowe” i po prostu należy go unikać.
underscore_d