(Contexte: j'ai une certaine expérience de la mise en œuvre de compilateurs C et C++.)
De longueur Variable des tableaux en C99 ont été essentiellement un faux-pas. Afin de soutenir Blaise, C99 eu à faire les concessions suivantes pour le sens commun:
sizeof x
n'est plus toujours une constante de compilation, le compilateur doit parfois générer du code pour évaluer un sizeof
-expression au moment de l'exécution.
Permettant à deux dimensions VLAs (int A[x][y]
) besoin d'une nouvelle syntaxe pour la déclaration des fonctions 2D VLAs comme paramètres: void foo(int n, int A[][*])
.
De moins en moins important dans le C++ monde, mais extrêmement important pour les C de cible du embarqués-systèmes de programmeurs, de la déclaration d'une VLA signifie mâchent un arbitrairement grande partie de votre pile. C'est une garantie de la pile de dépassement et de crash. (À tout moment, vous déclarez int A[n]
, vous êtes implicitement affirmer que vous avez 2 go de pile de rechange. Après tout, si vous savez "n
est certainement moins de 1000 ici", puis vous devez simplement déclarer int A[1000]
. La substitution de l'entier de 32 bits n
pour 1000
est un aveu que vous n'avez aucune idée de ce que le comportement de votre programme devrait être.)
Ok, donc passons à parler de C++ maintenant. En C++, nous avons la même forte distinction entre "type de système" et "système de valeur" que C89 n'... mais nous avons vraiment commencé à compter sur lui dans les moyens que C n'a pas. Par exemple:
template<typename T> struct S { ... };
int A[n];
S<decltype(A)> s; // equivalently, S<int[n]> s;
Si n
n'étaient pas une constante de compilation (c'est à dire, si A
étaient de variable du type modifié), alors que sur la terre serait le type d' S
? Serait - S
s'type aussi être déterminé qu'au moment de l'exécution?
Ce:
template<typename T> bool myfunc(T& t1, T& t2) { ... };
int A1[n1], A2[n2];
myfunc(A1, A2);
Le compilateur doit générer du code pour certaines instanciation d' myfunc
. Ce que le code devrait ressembler? Comment pouvons-nous statiquement générer ce code, si nous ne connaissons pas le type de l' A1
au moment de la compilation?
Pire, que si elle s'avère au moment de l'exécution n1 != n2
, de sorte qu' !std::is_same<decltype(A1), decltype(A2)>()
? Dans ce cas, l'appel à l' myfunc
ne devrait même pas compiler, parce que le modèle type de déduction doit échouer! Comment pourrions-nous nous en reproduire le comportement au moment de l'exécution?
Fondamentalement, C++ est en mouvement dans le sens de pousse de plus en plus de décisions en temps de compilation: modèle de génération de code, constexpr
l'évaluation de la fonction, et ainsi de suite. Pendant ce temps, C99 était occupé à pousser traditionnellement au moment de la compilation des décisions (par exemple, sizeof
) dans le runtime. Avec cela à l'esprit, est-il vraiment de sens de dépenser de l'effort d'essayer d'intégrer C99-style VLAs en C++?
Comme tous les autres répondeur l'a déjà souligné, C++ fournit beaucoup de tas de mécanismes d'allocation (std::unique_ptr<int[]> A = new int[n];
ou std::vector<int> A(n);
étant les plus évidents) quand vous voulez exprimer l'idée "je n'ai aucune idée de combien de RAM je pourrais en avoir besoin." Et le C++ fournit une chouette exception modèle de gestion pour faire face à l'inévitable situation que la quantité de RAM que vous avez besoin est supérieure à la quantité de RAM que vous avez. Mais j'espère que cette réponse vous donne une bonne idée de pourquoi C99-style VLAs étaient pas un bon ajustement pour le langage C++ et même pas vraiment un bon ajustement pour le C99. ;)