Notas sobre C ++: A inicialização de matrizes possui uma boa lista sobre a inicialização de matrizes. eu tenho um
int array[100] = {-1};
esperando que esteja cheio de -1, mas não, apenas o primeiro valor é e o restante é 0 misturado com valores aleatórios.
O código
int array[100] = {0};
funciona bem e define cada elemento como 0.
O que estou perdendo aqui .. Não é possível inicializá-lo se o valor não for zero?
E 2: a inicialização padrão (como acima) é mais rápida que o loop usual em toda a matriz e atribui um valor ou faz a mesma coisa?
{0}
não é um caso especial para estruturas nem matrizes. A regra é que elementos sem inicializador são inicializados como se tivessem0
um inicializador. Se houver agregados aninhados (por exemplostruct x array[100]
), os inicializadores serão aplicados aos não agregados na ordem "maior de linha"; chaves pode opcionalmente ser omitido fazendo isso.struct x array[100] = { 0 }
é válido em C; e válido em C ++, desde que o primeiro membro dostruct X
aceite0
como inicializador.{ 0 }
não é especial em C, mas é muito mais difícil definir um tipo de dados que não pode ser inicializado com ele, pois não há construtores e, portanto, não há maneira de deixar0
de ser implicitamente convertido e atribuído a algo .Respostas:
Usando a sintaxe que você usou,
diz "defina o primeiro elemento como
-1
e o restante como0
", pois todos os elementos omitidos estão definidos como0
.No C ++, para configurá-los todos
-1
, você pode usar algo comostd::fill_n
(de<algorithm>
):No C portátil, você precisa rolar seu próprio loop. Existem extensões do compilador ou você pode depender do comportamento definido pela implementação como um atalho, se isso for aceitável.
fonte
#include <algorithm>
é o cabeçalho certo,<vector>
pode ou não incluir-o indiretamente, isso dependeria da sua implementação.int
expandi-la para o inicializador da matriz.fill_n
para preencher uma matriz 2D inteira. Você precisa percorrer uma dimensão enquanto preenche a outra.std::fill_n
não é inicialização.Há uma extensão para o compilador gcc que permite a sintaxe:
Isso definiria todos os elementos para -1.
Isso é conhecido como "Inicializadores Designados", consulte aqui para obter mais informações.
Observe que isso não foi implementado para o compilador gcc c ++.
fonte
A página à qual você vinculou já deu a resposta para a primeira parte:
Não há uma maneira interna de inicializar toda a matriz para um valor diferente de zero.
Quanto ao que é mais rápido, aplica-se a regra usual: "O método que dá ao compilador a maior liberdade provavelmente é mais rápido".
simplesmente diz ao compilador "defina essas 100 polegadas para zero", que o compilador pode otimizar livremente.
é muito mais específico. Diz ao compilador para criar uma variável de iteração
i
, informa a ordem em que os elementos devem ser inicializados e assim por diante. Obviamente, é provável que o compilador otimize isso, mas o ponto é que aqui você está superespecificando o problema, forçando o compilador a trabalhar mais para obter o mesmo resultado.Finalmente, se você deseja definir a matriz para um valor diferente de zero, você deve (pelo menos em C ++) usar
std::fill
:Novamente, você pode fazer o mesmo com uma matriz, mas isso é mais conciso e oferece mais liberdade ao compilador. Você está apenas dizendo que deseja que toda a matriz seja preenchida com o valor 42. Você não diz nada sobre a ordem em que deve ser feita ou qualquer outra coisa.
fonte
O C ++ 11 tem outra opção (imperfeita):
fonte
std::fill(begin(a), end(a), -1)
Com {} você atribui os elementos como eles são declarados; o restante é inicializado com 0.
Se não houver
= {}
para inicializar, o conteúdo é indefinido.fonte
A página que você vinculou
Problema de velocidade: quaisquer diferenças seriam insignificantes para matrizes tão pequenas. Se você trabalha com matrizes grandes e a velocidade é muito mais importante que o tamanho, pode ter uma matriz const dos valores padrão (inicializados em tempo de compilação) e depois
memcpy
para a matriz modificável.fonte
Outra maneira de inicializar a matriz com um valor comum seria realmente gerar a lista de elementos em uma série de define:
A inicialização de uma matriz para um valor comum pode ser feita facilmente:
Nota: DUPx introduzido para ativar a substituição de macro nos parâmetros do DUP
fonte
No caso de uma matriz de elementos de byte único, você pode usar o memset para definir todos os elementos com o mesmo valor.
Há um exemplo aqui .
fonte
Usando
std::array
, podemos fazer isso de uma maneira bastante direta no C ++ 14. É possível fazer apenas no C ++ 11, mas um pouco mais complicado.Nossa interface é um tamanho em tempo de compilação e um valor padrão.
A terceira função é principalmente por conveniência, de modo que o usuário não precisa construir a
std::integral_constant<std::size_t, size>
si próprio, pois essa é uma construção bastante prolífica. O trabalho real é realizado por uma das duas primeiras funções.A primeira sobrecarga é bem direta: ela cria um
std::array
tamanho 0. Não há cópia necessária, apenas a construímos.A segunda sobrecarga é um pouco mais complicada. Ele encaminha o valor obtido como fonte e também constrói uma instância
make_index_sequence
e apenas chama alguma outra função de implementação. Como é essa função?Isso constrói os argumentos do primeiro tamanho - 1, copiando o valor que passamos. Aqui, usamos nossos índices variados do pacote de parâmetros como algo para expandir. Existem entradas size - 1 nesse pacote (conforme especificado na construção de
make_index_sequence
) e elas têm valores de 0, 1, 2, 3, ..., tamanho - 2. No entanto, não nos importamos com os valores ( então nós o lançamos para anular, para silenciar qualquer aviso do compilador). A expansão do pacote de parâmetros expande nosso código para algo assim (assumindo tamanho == 4):Usamos esses parênteses para garantir que a expansão variada do pacote
...
expanda o que queremos e também para garantir que estamos usando o operador vírgula. Sem os parênteses, parece que estamos passando um monte de argumentos para a inicialização de nossa matriz, mas, na verdade, estamos avaliando o índice, lançando-o para nulo, ignorando esse resultado nulo e retornando o valor, que é copiado na matriz .O argumento final, o que chamamos
std::forward
, é uma otimização menor. Se alguém passar uma std :: string temporária e disser "faça uma matriz de 5 delas", gostaríamos de ter 4 cópias e 1 movimentação, em vez de 5 cópias. Ostd::forward
garante que fazemos isso.O código completo, incluindo cabeçalhos e alguns testes de unidade:
fonte
non_copyable
tipo é realmente copiável por meio deoperator=
.non_copy_constructible
que seria um nome mais preciso para o objeto. No entanto, não há atribuição em nenhum lugar deste código, portanto, não importa para este exemplo.1) Quando você usa um inicializador, para uma estrutura ou uma matriz como essa, os valores não especificados são essencialmente construídos por padrão. No caso de um tipo primitivo como ints, isso significa que eles serão zerados. Observe que isso se aplica recursivamente: você pode ter uma matriz de estruturas contendo matrizes e, se especificar apenas o primeiro campo da primeira estrutura, todo o resto será inicializado com zeros e construtores padrão.
2) O compilador provavelmente irá gerar um código inicializador que seja pelo menos tão bom quanto você poderia fazer manualmente. Costumo preferir deixar o compilador fazer a inicialização para mim, quando possível.
fonte
Em C ++, também é possível usar meta programação e modelos variados. A seguinte postagem mostra como fazer isso: Crie programaticamente matrizes estáticas em tempo de compilação em C ++ .
fonte
Na linguagem de programação C ++ V4, o Stroustrup recomenda o uso de vetores ou valarrays sobre matrizes internas. Com os valarrarys, quando você os cria, você pode iniciá-los com um valor específico, como:
Para inicializar uma matriz com 7 membros, com "7777777".
Essa é uma maneira C ++ de implementar a resposta usando uma estrutura de dados C ++ em vez de uma matriz "C simples e antiga".
Eu mudei para usar o valarray como uma tentativa no meu código para tentar usar C ++ 'isms v. C'isms ....
fonte
Deve ser um recurso padrão, mas por algum motivo não está incluído no padrão C nem C ++ ...
No Fortran, você poderia fazer:
mas não possui números não assinados ...
Por que o C / C ++ não pode simplesmente implementá-lo. Isso é realmente tão difícil? É tão tolo ter que escrever isso manualmente para obter o mesmo resultado ...
E se fosse uma matriz de 1.000,00 bytes? Eu precisaria escrever um script para escrever para mim ou recorrer a hacks com assembly / etc. Isso não faz sentido.
É perfeitamente portátil, não há razão para não estar no idioma.
Basta invadir como:
Uma maneira de invadir isso é através do pré-processamento ... (O código abaixo não cobre casos extremos, mas é escrito para demonstrar rapidamente o que poderia ser feito.)
fonte
memset
isso, mesmo com a matriz "codificada".