length - ¿Hay alguna razón para tamaño cero std:: array en C++ 11?
function vector c++ (4)
Al igual que con otras clases de contenedor, es útil poder tener un objeto que represente una serie de elementos, y que sea posible que esa matriz esté o se vacíe. Si eso no fuera posible, entonces uno necesitaría crear otro objeto, o una clase de manejo, para representar ese estado de una manera legal. Tener esa habilidad ya contenida en todas las clases de contenedor, es muy útil. Al usarlo, uno solo necesita tener el hábito de relacionarse con el arreglo como un contenedor que podría estar vacío, y verificar el tamaño o índice antes de referirse a un miembro del mismo en los casos en que podría no señalar nada.
Considere la siguiente pieza de código, que es perfectamente aceptable por un compilador C ++ 11:
#include <array>
#include <iostream>
auto main() -> int {
std::array<double, 0> A;
for(auto i : A) std::cout << i << std::endl;
return 0;
}
De acuerdo con el estándar § 23.3.2.8 [Arrays de tamaño cero ]:
1
matriz deberá proporcionar soporte para el caso especialN == 0
.
2
En el caso de queN == 0
,begin() == end() ==
valor único. El valor de retorno de
data()
está especificado.
3
El efecto de llamar afront()
oback()
para una matriz de tamaño cero no está definido.
4
Memberswap()
funciónswap()
tendrá una especificación noexcept que es equivalente anoexcept(true)
.
Como se muestra arriba, std::array
s de tamaño cero son perfectamente permitidos en C ++ 11, en contraste con arreglos de tamaño cero (por ejemplo, int A[0];
) donde están explícitamente prohibidos, sin embargo, son permitidos por algunos compiladores ( ej., GCC) en el costo del comportamiento indefinido.
Considerando esta "contradicción", tengo las siguientes preguntas:
¿Por qué el comité de C ++ decidió permitir
std::array
s de tamaño cero?¿Hay algún uso valioso?
En realidad, hay bastantes casos en los que desea poder hacer esto. Está presente en muchos otros idiomas también. Por ejemplo, Java en realidad tiene Collections.emptyList()
que devuelve una lista que no es solo de tamaño cero, sino que no se puede expandir o cambiar de tamaño o modificar.
Un ejemplo de uso podría ser si tuviera una clase que representara un autobús y una lista de pasajeros dentro de esa clase. La lista puede tener una inicialización lenta, creada solo cuando sube el pasajero. Sin embargo, si alguien llama a getPassengers()
se puede devolver una lista vacía en lugar de crear una lista nueva cada vez para informar de que está vacía.
La devolución del valor nulo también funcionaría para la eficiencia interna de la clase, pero haría la vida mucho más complicada para todos los usuarios de la clase, ya que cada vez que llame a getPassengers()
tendrá que getPassengers()
el resultado. En cambio, si obtiene una lista vacía entonces siempre que su código no suponga que la lista no está vacía, no necesita ningún código especial para manejarlo como nulo.
Si tiene una función genérica, es malo si esa función se rompe al azar para parámetros especiales. Por ejemplo, digamos que podría tener una función de plantilla que tome N
elementos aleatorios de un vector:
template<typename T, size_t N>
std::array<T, N> choose(const std::vector<T> &v) {
...
}
No se gana nada si esto causa un comportamiento indefinido o errores del compilador si N
por alguna razón resulta ser cero.
Para las matrices en bruto, una razón detrás de la restricción es que no desea tipos con sizeof T == 0
, esto genera efectos extraños en combinación con la aritmética del puntero. Una matriz con cero elementos tendría el tamaño cero, si no agrega ninguna regla especial para ella.
Pero std::array<>
es una clase, y las clases siempre tienen tamaño> 0. Por lo tanto, no se encuentra con esos problemas con std::array<>
, y es preferible una interfaz consistente sin una restricción arbitraria del parámetro de la plantilla. .
Un uso que se me ocurre es que el retorno de matrices de longitud cero es posible y tiene una funcionalidad que se debe verificar específicamente.
Por ejemplo, consulte la documentación en la función std::array
empty()
. Tiene el siguiente valor de retorno:
true if the array size is 0, false otherwise.
http://www.cplusplus.com/reference/array/array/empty/
Creo que la capacidad de devolver y verificar matrices de 0 longitudes está en línea con el estándar para otras implementaciones de tipos stl, por ejemplo. Vectores y mapas y por lo tanto es útil.