286 votes

Initialisation de tous les éléments d'un tableau à une valeur par défaut en C++ ?

Notes C++ : Initialisation des tableaux possède une liste intéressante sur l'initialisation des tableaux. J'ai un

int array[100] = {-1};

Je m'attendais à ce qu'il soit rempli de -1 mais ce n'est pas le cas, seule la première valeur l'est et les autres sont des 0 mélangés à des valeurs aléatoires.

Le code

int array[100] = {0};

fonctionne très bien et met chaque élément à 0.

Qu'est-ce que je rate ici Ne peut-on pas l'initialiser si la valeur n'est pas nulle ?

Et 2 : Est-ce que l'initialisation par défaut (comme ci-dessus) est plus rapide que la boucle habituelle qui parcourt tout le tableau et assigne une valeur ou est-ce qu'elle fait la même chose ?

1 votes

Le comportement en C et C++ est différent. En C, {0} est un cas spécial pour un initialisateur de structure, mais pas pour les tableaux. int array[100]={0} devrait être identique à array[100]={[0]=0}, ce qui a pour effet secondaire de mettre à zéro tous les autres éléments. Un compilateur C ne devrait PAS se comporter comme vous le décrivez ci-dessus, au contraire int array[100]={-1} devrait mettre le premier élément à -1 et le reste à 0 (sans bruit). En C, si vous avez une struct x array[100], utiliser ={0} comme initialisateur n'est PAS valable. Vous pouvez utiliser {{0}} qui initialisera le premier élément et mettra à zéro tous les autres, ce qui dans la plupart des cas sera la même chose.

1 votes

@FredrikWidlund C'est la même chose dans les deux langues. {0} n'est pas un cas particulier pour les structs ou les arrays. La règle est que les éléments sans initialisateur sont initialisés comme s'ils avaient 0 pour un initialisateur. S'il existe des agrégats imbriqués (par ex. struct x array[100] ) alors les initialisateurs sont appliqués aux non-agrégats dans l'ordre "row-major" ; les accolades peuvent éventuellement être omises pour ce faire. struct x array[100] = { 0 } est valide en C ; et valide en C++ tant que le premier membre de struct X accepte 0 comme initialisateur.

1 votes

{ 0 } n'est pas spéciale en C, mais il est beaucoup plus difficile de définir un type de données qui ne peut pas être initialisé avec elle puisqu'il n'y a pas de constructeurs et donc aucun moyen d'arrêter 0 d'être implicitement converti et affecté à quelque chose .

391voto

Evan Teran Points 42370

En utilisant la syntaxe que vous avez utilisée,

int array[100] = {-1};

dit "mettre le premier élément à -1 et le reste à 0 "puisque tous les éléments omis sont mis à 0 .

En C++, pour les mettre tous à -1 vous pouvez utiliser quelque chose comme std::fill_n (de <algorithm> ):

std::fill_n(array, 100, -1);

En C portable, vous devez créer votre propre boucle. Il existe des extensions de compilateur ou vous pouvez dépendre du comportement défini par l'implémentation comme raccourci si cela est acceptable.

18 votes

Cela répond également à une question indirecte sur la façon de remplir "facilement" le tableau avec des valeurs par défaut. Merci.

0 votes

La règle "mettre le premier élément à -1 et les autres à 0" s'applique-t-elle également à C ?

0 votes

@MattJoiner : oui, je le crois.

143voto

Callum Points 891

Il existe une extension au compilateur gcc qui permet la syntaxe :

int array[100] = { [0 ... 99] = -1 };

Cela mettrait tous les éléments à -1.

C'est ce que l'on appelle les "initialisateurs désignés". ici pour de plus amples informations.

Notez que ceci n'est pas implémenté pour le compilateur c++ de gcc.

4 votes

Génial. Cette syntaxe semble également fonctionner dans clang (et peut donc être utilisée sur iOS/Mac OS X).

40voto

jalf Points 142628

La page à laquelle vous avez accédé donne déjà la réponse à la première partie :

Si une taille de tableau explicite est spécifiée, mais qu'une liste d'initialisation est spécifiée, le éléments non spécifiés sont mis à zéro.

Il n'existe pas de moyen intégré pour initialiser le tableau entier à une valeur non nulle.

Quant à savoir lequel est le plus rapide, la règle habituelle s'applique : "La méthode qui donne le plus de liberté au compilateur est probablement plus rapide".

int array[100] = {0};

indique simplement au compilateur "mettre ces 100 ints à zéro", ce que le compilateur peut optimiser librement.

for (int i = 0; i < 100; ++i){
  array[i] = 0;
}

est beaucoup plus spécifique. Elle indique au compilateur de créer une variable d'itération i il lui dit que commander dans lequel les éléments doivent être initialisés, et ainsi de suite. Bien sûr, le compilateur est susceptible d'optimiser tout cela, mais le fait est qu'ici vous surspécifiez le problème, forçant le compilateur à travailler plus dur pour arriver au même résultat.

Enfin, si vous souhaitez définir le tableau à une valeur non nulle, vous devez (en C++, du moins) utiliser la commande std::fill :

std::fill(array, array+100, 42); // sets every value in the array to 42

Encore une fois, vous pourriez faire la même chose avec un tableau, mais cette méthode est plus concise et donne plus de liberté au compilateur. Vous dites simplement que vous voulez que le tableau entier soit rempli avec la valeur 42. Vous ne dites rien sur l'ordre dans lequel cela doit être fait, ni rien d'autre.

5 votes

Bonne réponse. Notez qu'en C++ (pas en C) vous pouvez faire int array[100] = {} ; et donner au compilateur le plus de liberté :)

1 votes

D'accord, excellente réponse. Mais pour un tableau de taille fixe, il faudrait utiliser std::fill_n :-P.

10voto

0x6adb015 Points 1498

Avec {} vous assignez les éléments tels qu'ils sont déclarés ; le reste est initialisé avec 0.

S'il n'y a pas de = {} pour capitaliser, le contenu est indéfini.

8voto

laalto Points 50581

La page dont vous avez donné le lien indique

Si une taille de tableau explicite est spécifiée, mais qu'une liste d'initialisation plus courte est spécifiée, les éléments non spécifiés sont mis à zéro.

Problème de vitesse : Toute différence serait négligeable pour des tableaux aussi petits. Si vous travaillez avec de grands tableaux et que la vitesse est beaucoup plus importante que la taille, vous pouvez avoir un tableau const des valeurs par défaut (initialisé au moment de la compilation) et ensuite memcpy dans le tableau modifiable.

2 votes

Le memcpy n'est pas une très bonne idée, puisque cela serait comparable à la définition directe des valeurs en termes de vitesse.

1 votes

Je ne vois pas l'utilité de la copie et du tableau de const : Pourquoi ne pas créer le tableau modifiable en premier lieu avec les valeurs pré-remplies ?

0 votes

Merci pour l'explication de la vitesse et la façon de procéder si la vitesse est un problème avec une grande taille de tableau (ce qui est mon cas).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X