std::array
é muito superior aos arrays C. E mesmo se eu quiser interoperar com o código legado, posso apenas usar std::array::data()
. Existe alguma razão para eu querer uma matriz da velha escola?
std::array
é muito superior aos arrays C. E mesmo se eu quiser interoperar com o código legado, posso apenas usar std::array::data()
. Existe alguma razão para eu querer uma matriz da velha escola?
Respostas:
A menos que eu tenha esquecido algo (não segui as mudanças mais recentes no padrão muito de perto), a maioria dos usos dos arrays de estilo C ainda permanecem. std::array
permite a inicialização estática, mas ainda não contará os inicializadores para você. E uma vez que o único uso real de matrizes de estilo C antes std::array
era para tabelas inicializadas estaticamente ao longo das linhas de:
MyStruct const table[] =
{
{ something1, otherthing1 },
// ...
};
usando as funções usuais begin
e de end
modelo (adotadas em C ++ 11) para iterar sobre eles. Sem nunca mencionar o tamanho, que o compilador determina a partir do número de inicializadores.
EDIT: Outra coisa que esqueci: literais de string ainda são arrays de estilo C; ou seja, com tipo char[]
. Não acho que alguém excluiria o uso de literais de string só porque temos std::array
.
const char[]
Não. Para, uh, ser franco. E em 30 caracteres.
Claro, você precisa de arrays C para implementar std::array
, mas essa não é realmente uma razão para que um usuário deseje arrays C. Além disso, não, std::array
não tem menos desempenho do que um array C e tem uma opção de acesso com verificação de limites. E, finalmente, é completamente razoável para qualquer programa C ++ depender da biblioteca padrão - esse é o objetivo de ser padrão - e se você não tiver acesso a uma biblioteca padrão, então seu compilador não está em conformidade e o question é marcada como "C ++", não "C ++ e aquelas coisas não C ++ que perdem metade da especificação porque a consideraram inadequada.".
std::array
em uma implementação independente do C ++ 11, no entanto.
Parece que usar arrays multidimensionais é mais fácil com arrays C do que com std::array
. Por exemplo,
char c_arr[5][6][7];
em oposição a
std::array<std::array<std::array<char, 7>, 6>, 5> cpp_arr;
Também devido à propriedade de decaimento automático dos arrays C, c_arr[i]
no exemplo acima irá decair para um ponteiro e você só precisa passar as dimensões restantes como mais dois parâmetros. Meu ponto é que c_arr
não é caro copiar. No entanto, cpp_arr[i]
será muito caro copiar.
array
de uma função multidimensional para uma função sem perder as dimensões. E se você passá-lo para um template de função, então essa função pode deduzir tanto a dimensão quanto o tamanho de cada dimensão, ou apenas uma das duas. Isso pode ser interessante para bibliotecas de modelos científicos que trabalham principalmente em dimensões arbitrárias.
template <typename T, int M, int N> using array2d = std::array<std::array<T, N>, M>;
deve resolver qualquer um desses problemas.
c_arr
é muito caro para copiar! Você deve fornecer o código para fazer isso sozinho. O ponteiro para o qual ele decairá é um equivalente mais próximo a uma referência do que a uma cópia, e você pode usar std::array
para passar uma referência se for o que deseja.
std::size_t
, em vez de int
? desculpe por picuinhas, mas isso o tornaria universal.
size_t
se quiser, embora eu não consiga imaginar que existam muitos cenários em que matrizes com mais de 4 bilhões de linhas ou colunas sejam necessárias.
Como Sumant disse, arrays multidimensionais são muito mais fáceis de usar com arrays C embutidos do que com std::array
.
Quando aninhado, std::array
pode se tornar muito difícil de ler e desnecessariamente prolixo.
Por exemplo:
std::array<std::array<int, 3>, 3> arr1;
comparado com
char c_arr[3][3];
Além disso, nota que begin()
, end()
e size()
todos os valores sem sentido de retorno quando você ninho std::array
.
Por essas razões, criei meus próprios contêineres de array multidimensional de tamanho fixo array_2d
e array_3d
. Eles são análogos, std::array
mas para matrizes multidimensionais de 2 e 3 dimensões. Eles são mais seguros e não têm pior desempenho do que os arrays multidimensionais integrados. Não incluí um contêiner para matrizes multidimensionais com dimensões maiores que 3, pois são incomuns. Em C ++ 0x, uma versão de modelo variável pode ser feita que suporta um número arbitrário de dimensões.
Um exemplo da variante bidimensional:
//Create an array 3 x 5 (Notice the extra pair of braces)
fsma::array_2d <double, 3, 5> my2darr = {{
{ 32.19, 47.29, 31.99, 19.11, 11.19},
{ 11.29, 22.49, 33.47, 17.29, 5.01 },
{ 41.97, 22.09, 9.76, 22.55, 6.22 }
}};
A documentação completa está disponível aqui:
http://fsma.googlecode.com/files/fsma.html
Você pode baixar a biblioteca aqui:
arr[x][y]
, você não pode dizer se arr
é um array de arrays, um array de ponteiros, um ponteiro para um array ou um ponteiro para um ponteiro; todos para implementações são legítimos, dependendo de suas necessidades. E provavelmente a maioria dos casos de uso do mundo real para arrays multidimensionais exige que o tamanho seja determinado no tempo de execução.
Os arrays de estilo C disponíveis em C ++ são, na verdade, muito menos versáteis do que os arrays C reais. A diferença é que, em C, os tipos de array podem ter tamanhos de tempo de execução . O seguinte é um código C válido, mas não pode ser expresso com matrizes de estilo C C ++ nem com os array<>
tipos C ++ :
void foo(int bar) {
double tempArray[bar];
//Do something with the bar elements in tempArray.
}
Em C ++, você teria que alocar a matriz temporária no heap:
void foo(int bar) {
double* tempArray = new double[bar];
//Do something with the bar elements behind tempArray.
delete[] tempArray;
}
Isso não pode ser alcançado com std::array<>
, porque bar
não é conhecido em tempo de compilação, requer o uso de matrizes de estilo C em C ++ ou de std::vector<>
.
Embora o primeiro exemplo possa ser expresso com relativa facilidade em C ++ (embora exija new[]
e delete[]
), o seguinte não pode ser alcançado em C ++ sem std::vector<>
:
void smoothImage(int width, int height, int (*pixels)[width]) {
int (*copy)[width] = malloc(height*sizeof(*copy));
memcpy(copy, pixels, height*sizeof(*copy));
for(y = height; y--; ) {
for(x = width; x--; ) {
pixels[y][x] = //compute smoothed value based on data around copy[y][x]
}
}
free(copy);
}
A questão é que os ponteiros para as matrizes de linha int (*)[width]
não podem usar uma largura de tempo de execução em C ++, o que torna qualquer código de manipulação de imagem muito mais complicado em C ++ do que em C. Uma implementação C ++ típica do exemplo de manipulação de imagem ficaria assim:
void smoothImage(int width, int height, int* pixels) {
int* copy = new int[height*width];
memcpy(copy, pixels, height*width*sizeof(*copy));
for(y = height; y--; ) {
for(x = width; x--; ) {
pixels[y*width + x] = //compute smoothed value based on data around copy[y*width + x]
}
}
delete[] copy;
}
Este código faz exatamente os mesmos cálculos que o código C acima, mas precisa realizar o cálculo do índice manualmente onde quer que os índices sejam usados . Para o caso 2D, isso ainda é viável (embora venha com muitas oportunidades de errar no cálculo do índice). No entanto, fica realmente desagradável no caso 3D.
Gosto de escrever código em C ++. Mas sempre que preciso manipular dados multidimensionais, realmente me pergunto se devo mover essa parte do código para C.
gcc
por exemplo). O C11 tornou opcionais várias coisas interessantes, e não acho que seja porque eles queiram proibir o recurso. Eu tendo a ver isso como um sinal de que eles queriam abaixar o nível de escrever um compilador totalmente compatível com os padrões: VLAs são bastante difíceis de implementar e muitos códigos podem ser dispensados, então faz sentido para um novo compilador em algum novo plataforma para não ter que implementar VLAs imediatamente.
Pode ser que std::array
não seja lento. Mas eu fiz alguns benchmarking usando armazenamento simples e li do std :: array; Veja os resultados de benchmark abaixo (em W8.1, VS2013 Atualização 4):
ARR_SIZE: 100 * 1000
Avrg = Tick / ARR_SIZE;
test_arr_without_init
==>VMem: 5.15Mb
==>PMem: 8.94Mb
==>Tick: 3132
==>Avrg: 0.03132
test_arr_with_init_array_at
==>VMem: 5.16Mb
==>PMem: 8.98Mb
==>Tick: 925
==>Avrg: 0.00925
test_arr_with_array_at
==>VMem: 5.16Mb
==>PMem: 8.97Mb
==>Tick: 769
==>Avrg: 0.00769
test_c_arr_without_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 358
==>Avrg: 0.00358
test_c_arr_with_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 305
==>Avrg: 0.00305
De acordo com as marcas negativas, o código que usei está no pastebin ( link )
O código da classe de benchmark está aqui ;
Não sei muito sobre benchmarks ... Meu código pode estar com falhas
long test_arr_without_init() { return ARR_SIZE; }
void test_arr_without_init() {}
agora. Você realmente precisa passar por muitos obstáculos para ter certeza de que o código que está medindo é o código que deseja medir.
std::array
std::array
terá menos desempenho do que um array C.
at()
, não é operator[]
, apenas gosto std::vector
. Não há diminuição de desempenho ou inchaço de código std::array
, o compilador é projetado para otimizar esse tipo de coisa. E, é claro, a adição da função marcada é uma excelente ferramenta de depuração e uma grande vantagem. @Lou Franco: Todo código C ++ pode depender da biblioteca padrão - é para isso que serve. @Earlz: Se você não tem STL disponível, então não é C ++, e ponto final.
std::array
ser maior do que o uso de array C equivalente.