Como posso declarar e definir várias variáveis ​​em uma linha usando C ++?

173

Sempre achei que, se eu declarar essas três variáveis, todas elas terão o valor 0

int column, row, index = 0;

Mas acho que apenas o índice é igual a zero e os outros são lixo como 844553 e 2423445.

Como posso inicializar todas essas variáveis ​​para zero sem declarar cada variável em uma nova linha?

Sam
fonte
36
Cuidado com essas declarações multivariáveis ​​de uma linha. É mais fácil do que você pensa declarar um ponteiro int seguido por uma lista de números inteiros regulares ( int* a, b, c;não faz o que parece).
precisa
4
Existem apenas três variáveis, cara, escreva =0para cada uma em suas definições. E, se você realmente deseja muitas variáveis, tente uma matriz: int a[10]={0}inicializará cada uma a[i]em 0 para você.
Stan
O compilador não deve permitir que a construção se ele vai se comportar de forma diferente do que o que um programador razoável seria de esperar que ele faça ... imho
cph2117
1
@ cph2117 Um programador razoável pensaria 'hmm, essa sintaxe pode significar algumas coisas diferentes, dependendo de como a gramática liga as coisas' , procure o Padrão para descobrir o que é verdadeiro e siga em frente.
Underscore_d
Pare de fazer isso. Isso apenas torna o código mais difícil de ler. O objetivo de escrever código em uma linguagem de alto nível é facilitar a leitura de um mantenedor.
Martin York

Respostas:

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

Quando você declara:

int column, row, index = 0;

Somente o índice está definido como zero.

No entanto, você pode fazer o seguinte:

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

Mas, pessoalmente, prefiro o seguinte, que foi apontado.
É uma forma mais legível na minha opinião.

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

ou

int column = 0;
int row = 0;
int index = 0;
Matt
fonte
3
Entre os dois últimos, eu decido com base se os dois valores devem realmente ser do mesmo tipo ( bool previousInputValue, presentInputValue;) ou se são do mesmo tipo agora, mas não precisam ser ( uint8_t height, width;podem se transformar uint8_t height; uint16_t width;no futuro e deveriam ter sido uint8_t height; uint8_t width;começar com).
altendky
Porque escrever em uint8_t height; uint16_t width;vez de uint8_t height, width;salvar 10 caracteres no futuro. :-) é claro que você pode fazê-lo como quiser. Apenas certifique-se de que seja fácil de ler. Portanto, a última forma é a mais explícita.
Matt
A última forma é certamente a mais explícita ao declarar o tipo de cada variável e deixar claro que cada uma é inicializada. Dito isto, não está explícito se a coluna e a linha devem ou não ser do mesmo tipo ou não. Talvez nós dois preferimos a explicitação de int presentValue = 0; typeof(presentValue) previousValue = presentValue;, mas acredito que essa typeof()é uma extensão não padrão do GCC.
altendky
49

Como o @Josh disse, a resposta correta é:

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

Você precisará observar a mesma coisa com os ponteiros. Este:

int* a, b, c;

É equivalente a:

int *a;
int b;
int c;
Mateen Ulhaq
fonte
34
Eu odeio essa coisa de ponteiro, não faz sentido. O asterisco faz parte do tipo, portanto deve ser aplicado a todos eles. Imagine se unsigned long x, y;declarado xcomo unsigned longmas yapenas como unsigned, aka unsigned int! Isso é exatamente o mesmo! </rant>
Cam Jackson
6
Faz sentido. "int * a, b, c;"
21413 Jeroen
7
@JeroenBollen Bem, sim, faz sentido se você escrever seu asterisco ao lado do nome da variável em vez do tipo, mas isso por si só não faz sentido. Como eu disse acima, o asterisco é parte do tipo, não parte do nome, portanto deve ser agrupado com o tipo!
amigos estão dizendo sobre cam
11
Como um lado não, na verdade faz sentido o * não é necessariamente parte do tipo, como o int *ameio que *arepresenta um intvalor.
precisa saber é o seguinte
2
O ponto já foi levantado, mas apenas para adicionar a ele o nulo é essencialmente a falta de um tipo, mas você ainda pode fazer ponteiros para ele. Assim, por void* aque compilar e void *a, b, cnão. Essa racionalização funciona para mim.
Josh C
25

Se você declarar uma variável / objeto por linha, não apenas solucionará esse problema, como também tornará o código mais claro e evitará erros tolos ao declarar ponteiros.

Para responder diretamente à sua pergunta, você deve inicializar cada variável para 0 explicitamente. int a = 0, b = 0, c = 0;.

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

Observe que este formulário também funcionará com tipos personalizados, especialmente quando seus construtores usam mais de um argumento.

Michael Kristofik
fonte
2
e hoje em dia com inicialização uniforme (o C ++ 17 pendente corrigindo isso para auto...): int coluna { 0 } , linha { 0 } , índice { 0 } ;
underscore_d
5

A partir de 2k18, você pode usar Ligações Estruturadas :

#include <iostream>
#include <tuple>

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

Demo

ivaigult
fonte
4

Possíveis abordagens:

  • Inicialize todas as variáveis ​​locais com zero.
  • Tenha uma matriz memsetou {0}a matriz.
  • Torne global ou estático.
  • Coloque-os structe / memsetou tenha um construtor que os inicializaria em zero.
Ajay
fonte
#define COLUMN 0 #define ROW 1 #define INDEX 2 #define AR_SIZE 3 int Data [ AR_SIZE ]; // Apenas uma ideia.
Ajay
Desculpe, eu quis dizer, por que você incluiu a linha " Tem uma matriz, memset ou {0} a matriz "? Na sua resposta?
Mateen Ulhaq
memset (Data, 0, sizeof (Data)); // Se isso puder ser compactado logicamente.
Ajay
2

Eu não recomendaria isso, mas se você realmente gosta de ser uma linha e escrever 0 apenas uma vez, também pode fazer isso:

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

Como outros mencionaram, a partir do C ++ 17 em diante, você pode usar ligações estruturadas para várias atribuições de variáveis.

Combinando isso com std::arraye dedução argumento modelo podemos escrever uma função que atribui um valor a um número arbitrário de variáveis sem repetir o tipo ou 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
fonte
-13

Quando você declara uma variável sem inicializá-la, um número aleatório da memória é selecionado e a variável é inicializada com esse valor.

user3487742
fonte
7
Na verdade não. O compilador decide 'esta variável será no endereço xxx', o que aconteceu para estar em xxx endereço será o valor inicial a menos que seu conjunto para algo explicitamente (por inicializar ou atribuição)
PM100
3
@ pm100, embora seja melhor , e verdadeiro para qualquer implementação trivial que não se esforça para incomodar os usuários ... isso ainda é simplista demais ;-) já que o uso de uma variável não inicializada é UB, portanto, em teoria, tudo pode acontecer, incluindo qualquer código usando essa variável simplesmente sendo retirada do programa - o que é especialmente provável quando a otimização está em execução.
underscore_d
1
o valor dessa variável seria o que estava no endereço recebido, ou seja, lixo.
Pedro Vernetti
@PedroVernetti Não importa o que aconteceu no referido endereço antes de a nova variável ser declarada e obter o mesmo endereço. Se o usuário declara a nova variável sem inicializá-la com um valor e depois lê a variável antes de atribuir um valor a ela, o programa tem um comportamento indefinido. Isso é infinitamente pior que "aleatório" e "lixo" e só precisa ser evitado.
underscore_d