Notes C ++: l' initialisation des tableaux a une belle liste sur l'initialisation des tableaux. j'ai un
int array[100] = {-1};
s'attendant à ce qu'il soit plein de -1 mais ce n'est pas le cas, seule la première valeur est et les autres sont des 0 mélangés avec 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 manque ici .. Ne peut-on pas l'initialiser si la valeur n'est pas nulle?
Et 2: l'initialisation par défaut (comme ci-dessus) est-elle plus rapide que la boucle habituelle dans tout le tableau et attribue-t-elle une valeur ou fait-elle la même chose?
{0}
n'est pas un cas particulier pour les structures ni les tableaux. La règle est que les éléments sans initialiseur sont initialisés comme s'ils l'avaient été0
pour un initialiseur. S'il y a des agrégats imbriqués (par exemplestruct x array[100]
), les initialiseurs sont appliqués aux non-agrégats dans l'ordre "ligne principale"; les accolades peuvent éventuellement être omises en faisant cela.struct x array[100] = { 0 }
est valide en C; et valide en C ++ tant que le premier membre destruct X
accepte0
comme initialiseur.{ 0 }
n'est pas spécial en C, mais il est beaucoup plus difficile de définir un type de données qui ne peut pas être initialisé avec lui car il n'y a pas de constructeurs et donc aucun moyen d'empêcher0
d'être implicitement converti et assigné à quelque chose .Réponses:
En utilisant la syntaxe que vous avez utilisée,
dit "définir le premier élément sur
-1
et le reste sur0
" puisque tous les éléments omis sont définis sur0
.En C ++, pour les définir tous sur
-1
, vous pouvez utiliser quelque chose commestd::fill_n
(from<algorithm>
):Dans C portable, vous devez rouler 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.
la source
#include <algorithm>
est le bon en-tête,<vector>
peut-être l'inclure indirectement, cela dépendrait de votre implémentation.int
s souhaitée et la développer dans l'initialiseur du tableau.fill_n
pour remplir un tableau 2D entier. Vous devez parcourir une dimension en remplissant l'autre.std::fill_n
n'est pas l'initialisation.Il y a une extension au compilateur gcc qui permet la syntaxe:
Cela mettrait tous les éléments à -1.
C'est ce que l'on appelle les "initialiseurs désignés", voir ici pour plus d'informations.
Notez que cela n'est pas implémenté pour le compilateur gcc c ++.
la source
La page à laquelle vous avez lié a déjà donné la réponse à la première partie:
Il n'y a aucun moyen intégré d'initialiser le tableau entier à une valeur non nulle.
Quant à ce qui est plus rapide, la règle habituelle s'applique: "La méthode qui donne le plus de liberté au compilateur est probablement plus rapide".
dit simplement au compilateur de "mettre ces 100 pouces à zéro", que le compilateur peut optimiser librement.
est beaucoup plus spécifique. Il indique au compilateur de créer une variable d'itération
i
, il lui indique l' ordre dans lequel les éléments doivent être initialisés, etc. Bien sûr, le compilateur est susceptible d'optimiser cela, mais le fait est qu'ici vous surpé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 sur une valeur non nulle, vous devez (au moins en C ++) utiliser
std::fill
:Encore une fois, vous pouvez faire la même chose avec un tableau, mais c'est plus concis 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 dans quel ordre cela doit être fait, ou quoi que ce soit d'autre.
la source
C ++ 11 a une autre option (imparfaite):
la source
std::fill(begin(a), end(a), -1)
Avec {}, vous affectez les éléments tels qu'ils sont déclarés; le reste est initialisé avec 0.
S'il n'y a pas
= {}
à initialiser, le contenu n'est pas défini.la source
La page que vous avez liée aux états
Problème de vitesse: toute différence serait négligeable pour des baies aussi petites. 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), puis
memcpy
les placer dans le tableau modifiable.la source
Une autre façon d'initialiser le tableau à une valeur commune serait de générer réellement la liste des éléments dans une série de définitions:
L'initialisation d'un tableau à une valeur commune peut facilement être effectuée:
Remarque: DUPx introduit pour permettre la substitution de macro dans les paramètres de DUP
la source
Dans le cas d'un tableau d'éléments à un octet, vous pouvez utiliser memset pour définir tous les éléments à la même valeur.
Il y a un exemple ici .
la source
En utilisant
std::array
, nous pouvons le faire d'une manière assez simple en C ++ 14. Il est possible de le faire en C ++ 11 uniquement, mais légèrement plus compliqué.Notre interface est une taille au moment de la compilation et une valeur par défaut.
La troisième fonction est principalement pour la commodité, de sorte que l'utilisateur n'a pas à construire un
std::integral_constant<std::size_t, size>
même, car c'est une construction assez verbeuse. Le vrai travail est effectué par l'une des deux premières fonctions.La première surcharge est assez simple: il construit un
std::array
de taille 0. Il n'y a pas de copie nécessaire, nous le construisons simplement.La deuxième surcharge est un peu plus délicate. Il transmet la valeur obtenue en tant que source, et construit également une instance de
make_index_sequence
et appelle simplement une autre fonction d'implémentation. À quoi ressemble cette fonction?Cela construit les premiers arguments de taille - 1 en copiant la valeur que nous avons transmise. Ici, nous utilisons nos index de paquets de paramètres variadic comme quelque chose à développer. Il y a taille - 1 entrées dans ce pack (comme nous l'avons spécifié dans la construction de
make_index_sequence
), et elles ont des valeurs de 0, 1, 2, 3, ..., taille - 2. Cependant, nous ne nous soucions pas des valeurs ( nous l'avons donc annulé, pour désactiver tous les avertissements du compilateur). L'expansion du pack de paramètres étend notre code à quelque chose comme ceci (en supposant que la taille == 4):Nous utilisons ces parenthèses pour nous assurer que l'expansion du pack variadic
...
élargit ce que nous voulons, et également pour nous assurer que nous utilisons l'opérateur virgule. Sans les parenthèses, il semblerait que nous passions un tas d'arguments à l'initialisation de notre tableau, mais en réalité, nous évaluons l'index, le convertissons en vide, ignorant ce résultat vide, puis renvoyant la valeur, qui est copiée dans le tableau .Le dernier argument, celui que nous invoquons
std::forward
, est une optimisation mineure. Si quelqu'un passe dans une chaîne std :: temporaire et dit "faire un tableau de 5 d'entre eux", nous aimerions avoir 4 copies et 1 déplacement, au lieu de 5 copies. Lestd::forward
s'assure que nous le faisons.Le code complet, y compris les en-têtes et certains tests unitaires:
la source
non_copyable
type est en fait copiable au moyen deoperator=
.non_copy_constructible
serait un nom plus précis pour l'objet. Cependant, il n'y a aucune affectation nulle part dans ce code, donc cela n'a pas d'importance pour cet exemple.1) Lorsque vous utilisez un initialiseur, pour une structure ou un tableau comme celui-ci, les valeurs non spécifiées sont essentiellement construites par défaut. Dans le cas d'un type primitif comme les entiers, cela signifie qu'ils seront mis à zéro. Notez que cela s'applique récursivement: vous pouvez avoir un tableau de structures contenant des tableaux et si vous spécifiez uniquement le premier champ de la première structure, tout le reste sera initialisé avec des zéros et des constructeurs par défaut.
2) Le compilateur générera probablement un code d'initialisation au moins aussi bon que vous pourriez le faire à la main. J'ai tendance à préférer laisser le compilateur faire l'initialisation pour moi, lorsque cela est possible.
la source
En C ++, il est également possible d'utiliser la méta-programmation et les modèles variadiques. Le post suivant montre comment procéder: Créez par programme des tableaux statiques au moment de la compilation en C ++ .
la source
Dans le langage de programmation C ++ V4, Stroustrup recommande d'utiliser des vecteurs ou des valarrays sur des tableaux intégrés. Avec valarrary's, lorsque vous les créez, vous pouvez les initier à une valeur spécifique comme:
Pour initialiser un tableau de 7 membres de long avec "7777777".
Il s'agit d'une façon C ++ d'implémenter la réponse en utilisant une structure de données C ++ au lieu d'un tableau "plain old C".
Je suis passé à l'utilisation du valarray comme une tentative dans mon code pour essayer d'utiliser les ismes C ++ contre les c'ismes ....
la source
Devrait être une fonctionnalité standard, mais pour une raison quelconque, elle n'est pas incluse dans C standard ni C ++ ...
À Fortran, vous pourriez faire:
mais il n'a pas de numéros non signés ...
Pourquoi C / C ++ ne peut-il pas simplement l'implémenter. Est-ce vraiment si difficile? C'est tellement idiot d'avoir à écrire cela manuellement pour obtenir le même résultat ...
Et si c'était un tableau de 1 000,00 octets? J'aurais besoin d'écrire un script pour l'écrire pour moi, ou de recourir à des hacks avec assembly / etc. Ça n'a pas de sens.
Il est parfaitement portable, il n'y a aucune raison qu'il ne soit pas dans la langue.
Il suffit de le pirater comme:
Une façon de le pirater est via le prétraitement ... (Le code ci-dessous ne couvre pas les cas marginaux, mais est écrit pour démontrer rapidement ce qui pourrait être fait.)
la source
memset
, même avec le tableau "codé en dur".