Espacios de nombres
Variantes
Acciones

Declaración de arrays

De cppreference.com
< cpp‎ | language
 
 
 
 

Declara un objeto de tipo array.

Nota: Esta traducción utiliza el préstamo lingüístico del inglés array y su forma en plural, arrays, en cursivas, y no vector, matriz, arreglo o formación, todos términos que se han utilizado antes para describir un array.
La base de esta decisión tiene que ver con:
- el número de términos aceptables (vector, matriz, arreglo, formación);
- la colisión de nombres (p. ej., el nombre vector puede confundirse con el std::vector de la STL);
- la similitud limitada (p. ej., el uso de matriz denota un concepto matemático, pero más allá de la notación, no hay otro soporte para operaciones de "matrices" en el lenguaje C++, tal como multiplicación o inversión de matrices);
- la pregunta de cómo tratar con std::array y std::vector, que no pueden llamarse una matriz.

En la opinión del traductor, el uso del término array proporciona al lector un término que, aunque no existe en el español, presenta menos problemas para exponer.

Contenido

[editar]Sintaxis

Una declaración de array es cualquier declaración simple cuyo declarador de array tiene la forma:

declarador-nopuntero[expr(opcional)]atrib(opcional) (1)
declarador-nopuntero - cualquier declarador válido, pero si comienza con *, &, o &&, tiene que estar rodeado de paréntesis.
atrib(C++11) - lista opcional de atributos
expr - una expresión constante entera(hasta C++14)una expresión constante convertida de tipo std::size_t(desde C++14), que se evalúa a un valor mayor que cero

Una declaración de la forma T a[N];, declara que a es un objeto de array que consiste en N objetos asignados contiguamente de tipo T. Los elementos de un array están numerados 0, …, N - 1, y pueden ser accedidos con el operador de subíndice integrado [], de esta manera: a[0], …, a[N -1].

Los arrays pueden ser construídos a partir de cualquier tipo fundamental (excepto void), punteros, punteros a miembro, clases, enumeraciones, o a partir de otros arrays de límites conocidos (en tal caso se dice que el array es multidimensional). En otras palabras, solamente tipos de objeto (excepto los tipos de array de límite desconocido), pueden ser tipos de elemento de arrays. Los tipos de arrays de tipo de elemento incompleto también son tipos incompletos.

No existen arrays de referencias o arrays de funciones.

Aplicar calificadores-cv a un tipo array (a través de typedef o manipulación de tipo mediante plantillas) aplica los calificadores al tipo de elemento, pero cualquier tipo array cuyos elementos son de tipo calificado-cv se considera que tiene la misma calificación-cv.

// a y b tienen el mismo tipo calificado const "array de 5 const char"typedefconstchar CC; CC a[5]={};typedefchar CA[5];const CA b ={};

Al usarse con la expresión-new[], el tamaño de un array puede ser cero; tal array no tiene elementos:

int* p = new int[0];// acceder a p[0] o *p es indefinido delete[] p;// todavía se requiere limpieza

[editar]Asignación

Los objetos de tipo array no pueden ser modificados en su totalidad: aun cuando son lvalues (e.g. se puede tomar la dirección de un array), no pueden aparecer en el lado izquierdo del operador de asignación:

int a[3]={1, 2, 3}, b[3]={4, 5, 6};int(*p)[3]=&a;// de acuerdo: puede tomarse la dirección de a a = b;// ERROR: a es un arraystruct{int c[3];} s1, s2 ={3, 4, 5}; s1 = s2;// de acuerdo: operador de asignación de copia definido implícitamente// puede asignar datos miembro de tipo array

[editar]Decadencia de array a puntero

Existe una conversión implícita de lvalues y rvalues de tipo array a tipo puntero: construye un puntero al primer elemento de un array. Esta conversión se usa cada vez que los arrays aparecen en un contexto donde no se esperan arrays, sino punteros:

#include <iostream>#include <numeric>#include <iterator>   void g(int(&a)[3]){std::cout<< a[0]<<'\n';}   void f(int* p){std::cout<<*p <<'\n';}   int main(){int a[3]={1, 2, 3};int* p = a;   std::cout<< sizeof a <<'\n'// imprime el tamaño del array<< sizeof p <<'\n';// imprime el tamaño de un puntero   // donde se aceptan los arrays, pero no los punteros, solamente se pueden usar arrays: g(a);// de acuerdo: la función toma una array por referencia// g(p); // ERROR   for(int n: a)// de acuerdo: los arrays pueden usarse en bucle for basado en rangostd::cout<< n <<' ';// imprime los elementos del array// for(int n: p) // ERROR// std::cout << n << ' ';   std::iota(std::begin(a), std::end(a), 7);// de acuerdo: begin y end toman arrays// std::iota(std::begin(p), std::end(p), 7); // ERROR   // donde se aceptan los punteros, pero no los arrays, ambos pueden usarse: f(a);// de acuerdo: función toma un puntero f(p);// de acuerdo: función toma un puntero   std::cout<<*a <<'\n'// imprime el primer elemento<<*p <<'\n'// lo mismo<<*(a +1)<<' '<< a[1]<<'\n'// imprime el segundo elemento<<*(p +1)<<' '<< p[1]<<'\n';// lo mismo}


Además, durante la deducción de argumentos de plantillas, un array decae a un puntero si se pasa por valor:

template<typename T>void fun(T t){ ... }   int a[6]; ... fun(a);// T se deduce como int*

[editar]Arrays multidimensionales

Cuando el tipo de elemento de un array es otro array, se dice que el array es multidimensional:

// array de 2 arrays de 3 int cada unoint a[2][3]={{1, 2, 3}, // puede verse como una matriz de 2 × 3{4, 5, 6}};// con distribución de fila-mayor

Observa que cuando se aplica la decadencia de array a puntero, un array multidimensional se convierte a un puntero a su primer elemento (p. ej., un puntero a su primer fila o a su primer plano): la decadencia de array a puntero se aplica solamente una vez.

int a[2];// array de 2 intint* p1 = a;// a decae a un puntero al primer elemento de a   int b[2][3];// array de 2 arrays de 3 int// int** p2 = b; // ERROR: b no decae a int**int(*p2)[3]= b;// b decae a un puntero a la primer fila de 3 elementos de b   int c[2][3][4];// array de 2 arrays de 3 arrays de 4 int// int*** p3 = c; // ERROR: c no decae a int***int(*p3)[3][4]= c;// c decae a un puntero al primer plano de 3 × 4 elementos de c

[editar]Arrays de límite desconocido

Si se omite expr en la declaración de un array, el tipo declarado es de "array de límite desconocido de T", que es una clase de tipo incompleto, excepto cuando se usa en una declaración con un inicializador de agregado:

externint x[];// el tipo de x es "array de límite desconocido de int"int a[]={1, 2, 3};// el tipo de a es "array de 3 int"

Como los elementos de un array no pueden ser arrays de límite desconocido, los arrays multidimensionales no pueden tener un límite desconocido en una de sus dimensiones, excepto en la primera:

externint a[][2];// de acuerdo: array de límite desconocido de arrays de 2 intexternint b[2][];// ERROR: array tiene un elemento de tipo incompleto

Se pueden formar referencias y punteros a arrays de límite desconocido, pero no pueden inicializarse o asignarse a partir de arrays y punteros a arrays de límite conocido. Observa que en el lenguaje de programación C, los punteros a arrays de límite desconocido son compatibles con los punteros a arrays de límite conocido, y por lo tanto, convertibles y asignables en ambas direcciones.

externint a1[];int(&r1)[]= a1;// de acuerdoint(*p1)[]=&a1;// de acuerdoint(*q)[2]=&a1;// ERROR (pero de acuerdo en C)   int a2[]={1, 2, 3};int(&r2)[]= a2;// ERRORint(*p2)[]=&a2;// ERROR (pero de acuerdo en C)

Los punteros a arrays de límite desconocido no pueden participar en la artimética de punteros y no pueden ser usados a la izquierda del operador de subíndice, pero pueden ser desreferenciados. Los punteros y referencias a arrays de límite desconocido no pueden ser usados en parámetros de funciones(hasta C++14).

[editar]Rvalues de arrays

Aunque los arrays no pueden devolverse desde funciones por valor y no pueden ser objeto de la mayoría de las expresiones de conversión, pueden formarse prvalues de array usando un alias de tipo para construir un array temporal usando una conversión funcional inicializada con llaves.

Similar a los prvalues de clase, los prvalues de array se convierten en xvalues mediante la materialización temporal al evaluarse.(desde C++17)

Pueden formarse directamente xvalues de array accediendo un miembro del array de un rvalue de clase, o usando std::move, u otra conversión o llamada a función que devuelva una referencia rvalue.

#include <iostream>#include <type_traits>#include <utility>   void f(int(&&x)[2][3]){std::cout<< sizeof x <<'\n';}   struct X {int i[2][3];} x;   template<typename T>using identity = T;   int main(){std::cout<< sizeof X().i<<'\n';// tamaño del array f(X().i);// de acuerdo: se vincula a xvalue// f(x.i); // ERROR: no se puede vincular a lvalue   int a[2][3]; f(std::move(a));// de acuerdo: se vincula a xvalue   using arr_t =int[2][3]; f(arr_t{});// de acuerdo: se vincula a prvalue f(identity<int[][3]>{{1, 2, 3}, {4, 5, 6}});// de acuerdo: se vincula a prvalue   }

Salida:

24 24 24 24 24

[editar]Véase también

Documentación de C para Declaración de array
close