(Contexte: J'ai une certaine expérience de la mise en œuvre des compilateurs C et C ++.)
Les tableaux de longueur variable en C99 étaient fondamentalement un faux pas. Afin de soutenir les VLA, C99 a dû faire les concessions suivantes au bon sens:
sizeof x
n'est plus toujours une constante de compilation; le compilateur doit parfois générer du code pour évaluer une sizeof
expression au moment de l'exécution.
Permettre à deux dimensions VLA ( int A[x][y]
) nécessaire une nouvelle syntaxe pour déclarer des fonctions qui prennent 2D VLA comme paramètres: void foo(int n, int A[][*])
.
Moins important dans le monde C ++, mais extrêmement important pour le public cible de C des programmeurs de systèmes embarqués, déclarer un VLA signifie chomping un arbitrairement grand morceau de votre pile. Il s'agit d'un débordement de pile et d'un plantage garantis . (Chaque fois que vous déclarez int A[n]
, vous affirmez implicitement que vous avez 2 Go de pile à épargner. Après tout, si vous savez " n
est certainement inférieur à 1000 ici", alors vous déclareriez simplement int A[1000]
. La substitution de l'entier 32 bits n
pour 1000
est une admission que vous n'avez aucune idée du comportement de votre programme.)
Bon, passons maintenant à parler de C ++ maintenant. En C ++, nous avons la même distinction forte entre "système de types" et "système de valeurs" que C89… mais nous avons vraiment commencé à nous y fier d'une manière 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'était pas une constante de temps de compilation (c.-à-d., Si elle A
était de type modifié de façon variable), alors quel serait le type de ce type S
? Would S
type de » également être déterminée que lors de l' exécution?
Et ça:
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 une certaine instanciation de myfunc
. À quoi devrait ressembler ce code? Comment pouvons-nous générer statiquement ce code, si nous ne connaissons pas le type A1
au moment de la compilation?
Pire encore, que se passe-t-il s'il s'avère au moment de l'exécution que n1 != n2
, alors !std::is_same<decltype(A1), decltype(A2)>()
? Dans ce cas, l'appel à myfunc
ne devrait même pas être compilé , car la déduction du type de modèle devrait échouer! Comment pourrions-nous éventuellement émuler ce comportement lors de l'exécution?
Fondamentalement, C ++ évolue dans le sens de pousser de plus en plus de décisions au moment de la compilation : génération de code de modèle, constexpr
évaluation de fonction, etc. Pendant ce temps, C99 était occupé à pousser les décisions traditionnelles de compilation (par exemple sizeof
) dans le runtime . Dans cet esprit, est-il vraiment logique de consacrer des efforts à essayer d'intégrer des VLA de style C99 dans C ++?
Comme tous les autres répondeurs l'ont déjà souligné, C ++ fournit de nombreux mécanismes d'allocation de tas ( std::unique_ptr<int[]> A = new int[n];
ou std::vector<int> A(n);
étant les plus évidents) lorsque vous voulez vraiment transmettre l'idée "Je n'ai aucune idée de la quantité de RAM dont j'ai besoin". Et C ++ fournit un modèle astucieux de gestion des exceptions pour faire face à la situation inévitable où la quantité de RAM dont vous avez besoin est supérieure à la quantité de RAM dont vous disposez. Mais j'espère que cela réponse vous donne une bonne idée de pourquoi les VLA de style C99 n'étaient pas un bon ajustement pour C ++ - et pas vraiment même un bon ajustement pour C99. ;)
Pour plus d'informations sur le sujet, consultez N3810 «Alternatives pour les extensions de baie» , article d'octobre 2013 de Bjarne Stroustrup sur les VLA. Le POV de Bjarne est très différent du mien; N3810 se concentre davantage sur la recherche d'une bonne syntaxe ish C ++ pour les choses, et sur le découragement de l'utilisation de tableaux bruts en C ++, tandis que je me concentrais davantage sur les implications pour la métaprogrammation et le système de types. Je ne sais pas s'il considère que les implications de la métaprogrammation / système de types sont résolues, résolubles ou simplement sans intérêt.
Un bon article de blog qui touche bon nombre de ces mêmes points est "Utilisation légitime des tableaux à longueur variable" (Chris Wellons, 27/10/2019).