Une simple application de test :
cout << new int[0] << endl;
sorties :
0x876c0b8
On dirait que ça marche. Que dit la norme à ce sujet ? Est-il toujours légal d'"allouer" un bloc de mémoire vide ?
Une simple application de test :
cout << new int[0] << endl;
sorties :
0x876c0b8
On dirait que ça marche. Que dit la norme à ce sujet ? Est-il toujours légal d'"allouer" un bloc de mémoire vide ?
Je vous garantis que new int[0] vous coûte de l'espace supplémentaire puisque je l'ai testé.
Par exemple, l'utilisation de la mémoire de
int **arr = new int*[1000000000];
est significativement plus petit que
int **arr = new int*[1000000000];
for(int i =0; i < 1000000000; i++) {
arr[i]=new int[0];
}
L'utilisation de la mémoire du deuxième extrait de code moins celle du premier extrait de code correspond à la mémoire utilisée pour les nombreux nouveaux int[0].
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.
4 votes
+1 Question très intéressante - même si je ne suis pas sûr qu'elle ait beaucoup d'importance dans le code réel.
43 votes
@Zifre : Je pose la question par curiosité, mais cela pourrait avoir de l'importance dans le monde réel, par exemple lorsque la taille des blocs de mémoire alloués est calculée d'une certaine manière, et que le résultat du calcul peut être zéro, alors il n'y a pas de besoin direct d'ajouter des exceptions pour ne pas allouer des blocs de taille zéro . En effet, ils devraient être alloués et supprimés sans erreur (si seulement le bloc de taille zéro n'est pas déréférencé). D'une manière générale, cela permet d'élargir l'abstraction de ce qu'est un bloc de mémoire.
2 votes
@emg-2 : Dans votre exemple, cela n'aurait pas d'importance, car delete[] est parfaitement légal sur un pointeur NULL :-).
0 votes
@Evan : tu as raison :) un meilleur exemple : ce serait important s'il y avait une condition if() qui dépendrait de la valeur NULL, et par exemple arrêterait d'allouer plus de mémoire à cause d'une supposition erronée, qu'il n'y a plus de mémoire.
2 votes
Ce n'est qu'un lien indirect - c'est pourquoi je le commente ici - mais le C++ garantit à bien des égards que des objets distincts ont des adresses uniques... même s'ils n'ont pas explicitement besoin d'être stockés. Une expérience connexe consisterait à vérifier la taille d'une structure vide. Ou d'un tableau de cette structure.
2 votes
Pour compléter le commentaire de Shmoopty : En C++, il est courant d'avoir des objets de taille nulle, surtout lorsqu'on programme avec des modèles (par exemple, des modèles de classe de politique comme std::allocator). Le code générique peut avoir besoin d'allouer dynamiquement de tels objets et d'utiliser des pointeurs vers eux pour comparer l'identité des objets. C'est pourquoi l'opérateur new() renvoie des pointeurs uniques pour les requêtes de taille nulle. Bien que moins important/commun, le même raisonnement s'applique à l'allocation de tableaux et à l'opérateur new[]().
0 votes
Voyons ce qui se passe dans le code réel de la bibliothèque standard.
std::vector<double> v;
construit un vecteur vide (zéro élément). L'allocateur par défaut ne renvoie pasnullptr
(je viens de vérifier), mais il s'avère quev.data() == nullptr
Cela indique que dans le cas particulier où il n'y a pas d'élément, l'allocateur par défaut n'est pas utilisé (ou, ce qui est moins probable, écrasé). Si vous vous fiez à la sagesse de la bibliothèque standard (peut-être à la perspicacité de Stepanov), cela signifie que ce n'est probablement pas une bonne idée d'essayer d'allouer des tableaux dynamiques de taille zéro.(new int[0]
utilise un peu de mémoire car le `0 est stocké quelque part)0 votes
Je parie que la bibliothèque standard contient du code de ce type (par exemple dans le constructeur),
struct vector : ..., ptr_(num_elements==0?nullptr:allocator_.allocate(num_elements)), ...{...}
.