Je commence tout juste à entrer dans le C ++ et je veux prendre de bonnes habitudes. Si je viens d'allouer un tableau de type int
avec l' new
opérateur, comment puis-je les initialiser tous à 0 sans les parcourir tous moi-même? Dois-je simplement utiliser memset
? Existe-t-il une manière «C ++» de le faire?
176
&vector[0]
.Réponses:
C'est une fonctionnalité étonnamment peu connue de C ++ (comme en témoigne le fait que personne n'a encore donné cette réponse), mais elle a en fait une syntaxe spéciale pour l'initialisation de la valeur d'un tableau:
Notez que vous devez utiliser les parenthèses vides - vous ne pouvez pas, par exemple, utiliser
(0)
ou quoi que ce soit d'autre (c'est pourquoi cela n'est utile que pour l'initialisation de la valeur).Ceci est explicitement autorisé par ISO C ++ 03 5.3.4 [expr.new] / 15, qui dit:
et ne restreint pas les types pour lesquels cela est autorisé, alors que le
(expression-list)
formulaire est explicitement restreint par d'autres règles dans la même section de sorte qu'il n'autorise pas les types de tableau.la source
new int[10] {}
. Vous pouvez également fournir des valeurs pour initialiser avec:new int[10] {1,2,3}
En supposant que vous vouliez vraiment un tableau et non un std :: vector, la "manière C ++" serait la suivante
Mais sachez que sous le capot, il ne s'agit en fait que d'une boucle qui attribue à chaque élément la valeur 0 (il n'y a vraiment pas d'autre moyen de le faire, à l'exception d'une architecture spéciale avec un support au niveau matériel).
la source
Il existe un certain nombre de méthodes pour allouer un tableau de type intrinsèque et toutes ces méthodes sont correctes, mais celle à choisir dépend ...
Initialisation manuelle de tous les éléments en boucle
Utilisation de la
std::memset
fonction de<cstring>
Utilisation de l'
std::fill_n
algorithme de<algorithm>
Utilisation du
std::vector
conteneurSi C ++ 0x est disponible, en utilisant les fonctionnalités de la liste d'initialisation
la source
int array[SIZE] ={1,2,3,4,5,6,7};
notation, je peux utiliservoid rotateArray(int (& input)[SIZE], unsigned int k);
serait ma déclaration de fonction, que serait lors de l'utilisation de la première convention? toute suggestion?std::memset
soit faux - vous passez 10, il semble s'attendre à un nombre d'octets - voir en.cppreference.com/w/cpp/string/byte/memset . (Je pense que cela montre bien pourquoi devrait-on éviter une telle construction de bas niveau lorsque cela est possible.)Si la mémoire que vous allouez est une classe avec un constructeur qui fait quelque chose d'utile, l'opérateur new appellera ce constructeur et laissera votre objet initialisé.
Mais si vous allouez un POD ou quelque chose qui n'a pas de constructeur qui initialise l'état de l'objet, vous ne pouvez pas allouer de mémoire et initialiser cette mémoire avec l'opérateur new en une seule opération. Cependant, vous avez plusieurs options:
1) Utilisez plutôt une variable de pile. Vous pouvez allouer et initialiser par défaut en une seule étape, comme ceci:
2) utilisation
memset()
. Notez que si l'objet que vous allouez n'est pas un POD , le paramétrer est une mauvaise idée. Un exemple spécifique est que si vous memset une classe qui a des fonctions virtuelles, vous allez faire sauter la vtable et laisser votre objet dans un état inutilisable.3) De nombreux systèmes d'exploitation ont des appels qui font ce que vous voulez - allouer sur un tas et initialiser les données à quelque chose. Un exemple Windows serait
VirtualAlloc()
4) C'est généralement la meilleure option. Évitez du tout d'avoir à gérer la mémoire vous-même. Vous pouvez utiliser les conteneurs STL pour faire à peu près tout ce que vous feriez avec de la mémoire brute, y compris l'allocation et l'initialisation d'un seul coup:
la source
Oui il y a:
Utilisez un vecteur au lieu d'un tableau alloué dynamiquement. Les avantages incluent ne pas avoir à se soucier de supprimer explicitement le tableau (il est supprimé lorsque le vecteur sort de la portée) et aussi que la mémoire est automatiquement supprimée même s'il y a une exception levée.
Edit: Pour éviter d'autres votes négatifs au volant de personnes qui ne prennent pas la peine de lire les commentaires ci-dessous, je dois préciser que cette réponse ne dit pas que le vecteur est toujours la bonne réponse. Mais c'est certainement une manière plus C ++ que "manuellement" de s'assurer de supprimer un tableau.
Désormais, avec C ++ 11, il existe également std :: array qui modélise un tableau de taille constante (vs un vecteur capable de croître). Il existe également std :: unique_ptr qui gère un tableau alloué dynamiquement (qui peut être combiné avec l'initialisation comme répondu dans d'autres réponses à cette question). N'importe lequel de ceux-ci est un moyen plus C ++ que la gestion manuelle du pointeur vers le tableau, à mon humble avis.
la source
std::vector
au lieu de tableaux alloués dynamiquement? Quels sont les avantages de l'utilisation d'un tableau sur un vecteur, et vice versa?std::vector
.vector
partout quel que soit le contexte s'appelle «Ecrire du code Java en C ++».std::fill
est un moyen. Prend deux itérateurs et une valeur pour remplir la région. Cela, ou la boucle for, serait (je suppose) la manière la plus C ++.Pour définir un tableau de types entiers primitifs à 0 spécifiquement,
memset
c'est bien, même si cela peut soulever des sourcils. Considérez égalementcalloc
, bien qu'il soit un peu gênant à utiliser à partir de C ++ en raison de la distribution.Pour ma part, j'utilise presque toujours une boucle.
(Je n'aime pas remettre en question les intentions des gens, mais il est vrai que
std::vector
, toutes choses étant égales par ailleurs, préférable à l'utilisationnew[]
.)la source
vous pouvez toujours utiliser memset:
la source
memset
, mais je n'étais pas sûr que c'était la manière C ++ d'aborder le problème.10 * sizeof( *myArray )
est plus documenté et à l'épreuve des changements que10 * sizeof( int )
.En règle générale, pour les listes d'éléments dynamiques, vous utilisez un fichier
std::vector
.En général, j'utilise memset ou une boucle pour l'allocation dynamique de la mémoire brute, en fonction de la façon dont je prévois que cette zone de code sera à l'avenir.
la source