(Antecedentes: tengo algo de experiencia en la implementación de compiladores C y C ++).
Las matrices de longitud variable en C99 fueron básicamente un paso en falso. Para soportar los VLA, C99 tuvo que hacer las siguientes concesiones al sentido común:
sizeof x
ya no es siempre una constante de tiempo de compilación; el compilador a veces debe generar código para evaluar una sizeof
expresión en tiempo de ejecución.
Permitir VLA bidimensionales (int A[x][y]
) necesaria una nueva sintaxis para declarar funciones que toman 2D VLA como parámetros: void foo(int n, int A[][*])
.
Menos importante en el mundo de C ++, pero extremadamente importante para el público objetivo de programadores de sistemas integrados de C, declarar un VLA significa cortar una porción arbitrariamente grande de su pila. Este es un desbordamiento de pila y un bloqueo garantizados . (Cada vez que declaras int A[n]
, estás afirmando implícitamente que tienes 2GB de pila de sobra. Después de todo, si sabes que " n
definitivamente es menos de 1000 aquí", entonces simplemente declararías int A[1000]
. Sustituyendo el entero de 32 bitsn
para 1000
es una admisión que no tienes idea de cuál debería ser el comportamiento de tu programa).
Bien, pasemos ahora a hablar de C ++. En C ++, tenemos la misma distinción fuerte entre "sistema de tipos" y "sistema de valores" que C89 ... pero realmente hemos comenzado a confiar en ella de formas que C no tiene. Por ejemplo:
template<typename T> struct S { ... };
int A[n];
S<decltype(A)> s; // equivalently, S<int[n]> s;
Si n
no fuera una constante de tiempo de compilación (es decir, si A
fuera de tipo variablemente modificado), entonces ¿cuál sería el tipo de S
? Would S
tipo 's también se determinaría solo en tiempo de ejecución?
¿Qué hay de esto?
template<typename T> bool myfunc(T& t1, T& t2) { ... };
int A1[n1], A2[n2];
myfunc(A1, A2);
El compilador debe generar código para alguna instanciación de myfunc
. ¿Cómo debería ser ese código? ¿Cómo podemos generar estáticamente ese código, si no sabemos el tipo deA1
en tiempo de compilación?
Peor, ¿y si resulta que en tiempo de ejecución eso n1 != n2
, así que !std::is_same<decltype(A1), decltype(A2)>()
? En ese caso, la llamada a myfunc
ni siquiera debería compilar , ¡porque la deducción de tipo de plantilla debería fallar! ¿Cómo podríamos emular ese comportamiento en tiempo de ejecución?
Básicamente, C ++ se está moviendo en la dirección de impulsar más y más decisiones en tiempo de compilación : generación de código de plantilla, constexpr
evaluación de funciones, etc. Mientras tanto, C99 estaba ocupado empujando decisiones tradicionalmente en tiempo de compilación (por ejemplo sizeof
) en el tiempo de ejecución . Con esto en mente, ¿tiene sentido gastar algún esfuerzo? tratando de integrar VLA de estilo C99 en C ++?
Como todos los demás respondedores ya han señalado, C ++ proporciona muchos mecanismos de asignación de almacenamiento dinámico ( std::unique_ptr<int[]> A = new int[n];
o std::vector<int> A(n);
son los obvios) cuando realmente desea transmitir la idea "No tengo idea de la cantidad de RAM que podría necesitar". Y C ++ proporciona un ingenioso modelo de manejo de excepciones para lidiar con la situación inevitable de que la cantidad de RAM que necesita es mayor que la cantidad de RAM que tiene. Pero es de esperar que esta respuesta le dé una buena idea de por qué los VLA de estilo C99 no se ajustaban bien a C ++, y ni siquiera se ajustaban bien a C99. ;)
Para obtener más información sobre el tema, consulte N3810 "Alternativas para extensiones de matriz" , documento de Bjarne Stroustrup de octubre de 2013 sobre VLA. El punto de vista de Bjarne es muy diferente al mío; N3810 se enfoca más en encontrar una buena sintaxis ish de C ++ para las cosas y en desalentar el uso de matrices en bruto en C ++, mientras que me concentré más en las implicaciones para la metaprogramación y el sistema de tipos. No sé si considera las implicaciones de metaprogramación / sistema de tipos resueltas, solucionables o simplemente sin interés.
Una buena publicación de blog que alcanza muchos de estos mismos puntos es "Uso legítimo de matrices de longitud variable" (Chris Wellons, 2019-10-27).