Pourquoi les tableaux ne peuvent-ils pas être passés comme arguments de fonction ?
Ils le peuvent :
void foo(const int (&myArray)[5]) {
// `myArray` is the original array of five integers
}
En termes techniques, le type de l'argument à foo
est "référence à un tableau de 5 const
int
s" ; avec les références, on peut passer le réel l'objet autour ( clause de non-responsabilité : la terminologie varie selon le niveau d'abstraction) .
Ce que vous ne pouvez pas faire, c'est passer par valeur car, pour des raisons historiques, nous n'allons pas copie les tableaux. Au lieu de cela, tenter de passer un tableau par valeur dans une fonction (ou, pour passer un copie d'un tableau) conduit son nom à se décomposer en un pointeur. ( certaines ressources se trompent ! )
Les noms de tableaux se décomposent en pointeurs pour le passage par valeur.
Cela signifie :
void foo(int* ptr);
int ar[10]; // an array
foo(ar); // automatically passing ptr to first element of ar (i.e. &ar[0])
Il y a aussi le très trompeur "sucre syntaxique" qui regarde comme vous pouvez passer un tableau de longueur arbitraire par valeur :
void foo(int ptr[]);
int ar[10]; // an array
foo(ar);
Mais, en fait, vous ne faites que passer un pointeur (vers le premier élément du fichier ar
). foo
est le même qu'en haut !
Tant que nous y sommes, la fonction suivante également n'a pas vraiment la signature qu'il semble avoir. Regardez ce qui se passe lorsque nous essayons d'appeler cette fonction sans la définir :
void foo(int ar[5]);
int main() {
int ar[5];
foo(ar);
}
// error: undefined reference to `func(int*)'
Alors foo
prend int*
en fait, no int[5]
!
( Démonstration en direct. )
Mais vous pouvez le contourner !
Vous pouvez contourner ce problème en enveloppant le tableau dans un struct
o class
car l'opérateur de copie par défaut sera copier le tableau :
struct Array_by_val
{
int my_array[10];
};
void func (Array_by_val x) {}
int main() {
Array_by_val x;
func(x);
}
Ce comportement est quelque peu déroutant.
Ou, mieux, une approche générique de type "pass-by-reference".
En C++, avec un peu de magie des modèles, nous pouvons rendre une fonction à la fois réutilisable et capable de recevoir un tableau :
template <typename T, size_t N>
void foo(const T (&myArray)[N]) {
// `myArray` is the original array of N Ts
}
Mais on ne peut toujours pas en passer une par valeur. Quelque chose à retenir.
L'avenir...
Et comme C++11 se profile à l'horizon et que la prise en charge de C++0x est en bonne voie dans les chaînes d'outils grand public, vous pouvez utiliser l'adorable outil std::array
hérité de Boost ! Je laisse au lecteur le soin de faire des recherches à ce sujet.