arrays `` - ¿Hay alguna razón para tamaño cero std::array en C++11?




vector arreglos (5)

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. .

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 especial N == 0 .

2 En el caso de que N == 0 , begin() == end() == valor único. El valor de retorno de
data() está especificado.

3 El efecto de llamar a front() o back() para una matriz de tamaño cero no está definido.

4 Member swap() función swap() tendrá una especificación noexcept que es equivalente a noexcept(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?


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.


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.


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.


La mejor manera en mi opinión es usar la función Array.forEach. Si no puede usar eso, sugeriría obtener el polyfill de MDN para que esté disponible, es sin duda la forma más segura de iterar sobre una matriz en JavaScript.

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

Entonces, como otros han sugerido, esto es casi siempre lo que quieres:

var numbers = [1,11,22,33,44,55,66,77,88,99,111];
var sum = 0;
numbers.forEach(function(n){
  sum += n;
});

Esto garantiza que todo lo que necesite en el alcance del procesamiento de la matriz se mantenga dentro de ese alcance, y que solo está procesando los valores de la matriz, no las propiedades del objeto y otros miembros, que es lo que hace ... en.

en la mayoría de los casos, el uso de un estilo c normal para el bucle funciona, es importante recordar que todo dentro del bucle comparte su alcance con el resto de su programa, el {} no crea un nuevo alcance.

Por lo tanto:

var sum = 0;
var numbers = [1,11,22,33,44,55,66,77,88,99,111];

for(var i = 0; i<numbers.length; ++i){ 
  sum += numbers[i];
}

alert(i);

emitirá "11", que puede o no ser lo que desea.

Ejemplo de jsFiddle en funcionamiento: https://jsfiddle.net/workingClassHacker/pxpv2dh5/7/







c++ arrays c++11 c++14 stdarray