¿Cómo puedo declarar y definir múltiples variables en una línea usando C ++?

173

Siempre pensé que si declaraba estas tres variables, todas tendrían el valor 0

int column, row, index = 0;

Pero encuentro que solo el índice es igual a cero y los otros son basura como 844553 y 2423445.

¿Cómo puedo inicializar todas estas variables a cero sin declarar cada variable en una nueva línea?

Sam
fuente
36
Cuidado con esas declaraciones de una variable y múltiples variables. Es más fácil de lo que piensas declarar un puntero int seguido de una lista de enteros regulares ( int* a, b, c;no hace lo que parece).
Chris Eberle
44
Solo hay tres variables, amigo, escribe =0para cada una en sus definiciones. Y, si realmente quieres muchas variables, prueba una matriz: int a[10]={0}inicializará cada una a[i]a 0 por ti.
Stan
El compilador no debe permitir que el constructo si va a comportarse de manera diferente a lo que un programador razonable esperar que hacer ... en mi humilde opinión
cph2117
1
@ cph2117 Un programador razonable pensaría 'hmm, esta sintaxis podría significar un par de cosas diferentes dependiendo de cómo la gramática une las cosas' , busque el Estándar para descubrir cuál es la verdad y continúe.
underscore_d
Deja de hacer esto. Simplemente hace que el código sea más difícil de leer. El objetivo de escribir código en un lenguaje de alto nivel es simplificar la lectura de un responsable.
Martin York

Respuestas:

202
int column = 0, row = 0, index = 0;
Josh
fuente
162

Cuando declaras:

int column, row, index = 0;

Solo el índice se establece en cero.

Sin embargo, puede hacer lo siguiente:

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

Pero personalmente prefiero lo siguiente que se ha señalado.
Es una forma más legible en mi opinión.

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

o

int column = 0;
int row = 0;
int index = 0;
Mate
fuente
3
Entre los dos últimos decido en función de si los dos valores deben ser realmente del mismo tipo ( bool previousInputValue, presentInputValue;) o si simplemente son del mismo tipo ahora pero realmente no necesitan serlo ( uint8_t height, width;podría convertirse uint8_t height; uint16_t width;en el futuro y debería haber sido uint8_t height; uint8_t width;para empezar).
altendky
Porque escribir en uint8_t height; uint16_t width;lugar de uint8_t height, width;guardar 10 caracteres en el futuro. :-) por supuesto, puedes hacerlo como quieras. Solo asegúrate de que sea fácil de leer. Entonces la última forma es la más explícita.
Matt
La última forma es sin duda la más explícita al indicar el tipo de cada variable y dejar en claro que cada una se inicializa. Dicho esto, no es explícito acerca de si se espera que la columna y la fila sean del mismo tipo o no. Tal vez ambos preferiríamos la explicidad de int presentValue = 0; typeof(presentValue) previousValue = presentValue;, pero creo que typeof()es una extensión GCC no estándar.
altendky
49

Como dijo @Josh, la respuesta correcta es:

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

Tendrá que estar atento a lo mismo con los punteros. Esta:

int* a, b, c;

Es equivalente a:

int *a;
int b;
int c;
Mateen Ulhaq
fuente
34
Odio esa cosa del puntero, no tiene sentido. El asterisco es parte del tipo, por lo que debería aplicarse a todos ellos. ¡Imagínese si se unsigned long x, y;declara xcomo unsigned longpero ysolo unsigned, aka unsigned int! Eso es exactamente lo mismo! </rant>
Cam Jackson
66
Que tiene sentido. "int * a, b, c;"
Jeroen
77
@JeroenBollen Bueno, sí, tiene sentido si escribes tus asteriscos de puntero junto al nombre de la variable en lugar del tipo, pero eso en sí mismo no tiene ningún sentido. Como dije anteriormente, el asterisco es parte del tipo, no parte del nombre, por lo que debe agruparse con el tipo.
Cam Jackson
11
Como un lado no, en realidad tiene sentido que el * no sea necesariamente parte del tipo, como el int *amedio que *arepresenta un intvalor.
mdenton8
2
El punto ya se ha hecho, pero solo para agregarle vacío es esencialmente la falta de un tipo, pero aún puede hacer punteros a él. Por lo tanto, ¿por qué void* acompilará y void *a, b, cno lo hará? Esta racionalización funciona para mí.
Josh C
25

Si declara una variable / objeto por línea, no solo resuelve este problema, sino que aclara el código y evita errores tontos al declarar punteros.

Sin embargo, para responder directamente a su pregunta, debe inicializar cada variable a 0 explícitamente. int a = 0, b = 0, c = 0;.

Mark B
fuente
16
int column(0), row(0), index(0);

Tenga en cuenta que este formulario también funcionará con tipos personalizados, especialmente cuando sus constructores toman más de un argumento.

Michael Kristofik
fuente
2
y hoy en día con inicialización uniforme (pendiente C ++ 17 que arregla esto para auto...): int columna { 0 } , fila { 0 } , índice { 0 } ;
underscore_d
5

A partir de 2k18, puede usar enlaces estructurados :

#include <iostream>
#include <tuple>

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

Demo

ivaigult
fuente
4

Posibles enfoques:

  • Inicialice todas las variables locales con cero.
  • Tener una matriz, memseto {0}la matriz.
  • Hazlo global o estático.
  • Póngalos structy, memseto tenga un constructor que los inicialice a cero.
Ajay
fuente
#define COLUMN 0 #define ROW 1 #define INDEX 2 #define AR_SIZE 3 int Data [ AR_SIZE ]; // Solo una idea.
Ajay
Lo siento, quise decir, ¿por qué incluiste la línea " Tener una matriz, memset o {0} la matriz " en tu respuesta?
Mateen Ulhaq
memset (Datos, 0, tamaño de (Datos)); // Si esto se puede empaquetar lógicamente.
Ajay
2

No recomendaría esto, pero si realmente te gusta ser una línea y solo escribir 0 una vez, también puedes hacer esto:

int row, column, index = row = column = 0;
Levi Uzodike
fuente
0

Como otros han mencionado, desde C ++ 17 en adelante puedes usar enlaces estructurados para múltiples asignaciones de variables.

Combinando esto con std::arrayy deducción de argumento de plantilla podemos escribir una función que asigna un valor a un número arbitrario de variables sin repetir el tipo o valor .

#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
fuente
-13

Cuando declara una variable sin inicializarla, se selecciona un número aleatorio de la memoria y la variable se inicializa a ese valor.

usuario3487742
fuente
77
realmente no. El compilador decide 'esta variable estará en la dirección xxx', lo que sucedió en la dirección xxx será el valor inicial a menos que se establezca explícitamente (por inicialización o asignación)
pm100
3
@ pm100, aunque es mejor , y es cierto para cualquier implementación trivial que no se esfuerce por hostigar a los usuarios ... eso sigue siendo demasiado simple ;-) ya que el uso de una variable no inicializada es UB, por lo que, en teoría, puede suceder cualquier cosa, incluido cualquier código usando esa variable simplemente siendo eliminada del programa, lo cual es especialmente probable cuando la optimización está en juego.
underscore_d
1
el valor de esa variable sería lo que estaba en la dirección que obtuvo, es decir, basura.
Pedro Vernetti
@PedroVernetti No importa lo que sucedió en dicha dirección antes de que se declarara la nueva variable y se obtuviera la misma dirección. Si el usuario declara la nueva variable sin inicializarla con un valor y luego lee la variable antes de asignarle un valor, el programa tiene un comportamiento indefinido. Eso es infinitamente peor que "aleatorio" y "basura" y solo debe evitarse.
underscore_d