web-dev-qa-db-fra.com

L'opérateur new initialise la mémoire à zéro

Il y a un tel code:

#include <iostream>

int main(){
  unsigned int* wsk2 = new unsigned int(5);
  std::cout << "wsk2: " << wsk2 << " " << *wsk2 << std::endl;
  delete wsk2;
  wsk2 = new unsigned int;
  std::cout << "wsk2: " << wsk2 << " " << *wsk2 << std::endl;
  return 0;
}

Résultat:

wsk2: 0x928e008 5
wsk2: 0x928e008 0

J'ai lu que new n'initialise pas la mémoire avec des zéros. Mais ici, il semble que ce soit le cas. Comment ça marche?

65
scdmb

Il existe deux versions:

wsk = new unsigned int;      // default initialized (ie nothing happens)
wsk = new unsigned int();    // zero    initialized (ie set to 0)

Fonctionne également pour les tableaux:

wsa = new unsigned int[5];   // default initialized (ie nothing happens)
wsa = new unsigned int[5](); // zero    initialized (ie all elements set to 0)

En réponse au commentaire ci-dessous.

Euh ... êtes-vous sûr que new unsigned int[5]() zéros les entiers?

Apparemment oui:

[C++ 11: 5.3.4/15]: Une nouvelle expression qui crée un objet de type T initialise cet objet comme suit: Si le nouvel initialiseur est omis, l'objet est initialisé par défaut (8.5); si aucune initialisation n'est effectuée, l'objet a une valeur indéterminée. Sinon, le nouvel initialiseur est interprété selon les règles d’initialisation de 8.5 pour l’initialisation directe.

#include <new>
#include <iostream>


int main()
{
    unsigned int   wsa[5] = {1,2,3,4,5};

    // Use placement new (to use a know piece of memory).
    // In the way described above.
    // 
    unsigned int*    wsp = new (wsa) unsigned int[5]();

    std::cout << wsa[0] << "\n";   // If these are zero then it worked as described.
    std::cout << wsa[1] << "\n";   // If they contain the numbers 1 - 5 then it failed.
    std::cout << wsa[2] << "\n";
    std::cout << wsa[3] << "\n";
    std::cout << wsa[4] << "\n";
}

Résultats:

> g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-Apple-darwin13.2.0
Thread model: posix
> g++ t.cpp
> ./a.out
0
0
0
0
0
>
161
Martin York

operator new n’est pas sûr d’initialiser la mémoire, et le new-expression qui alloue un unsigned int sans new-initializer laisse l'objet avec une valeur indéterminée.

La lecture de la valeur d'un objet non initialisé entraîne comportement non défini. comportement indéfini inclut l'évaluation à la valeur zéro, sans effet néfaste, mais peut entraîner des incidents, vous devez donc éviter de les provoquer.

Dans C++ 11, le langage utilisé est que les objets alloués sont initialisé par défaut, ce qui pour les types non-classes signifie qu'aucune initialisation n'est effectuée. Ceci est différent de la signification de default-initialized en C++ 03.

19
CB Bailey

Avec certains compilateurs, la version de débogage de new initialisera les données, mais vous ne pouvez absolument pas vous fier à rien.

Il est également possible que la mémoire ne contienne que 0 d'une utilisation précédente. Ne supposez pas que rien ne soit arrivé à la mémoire entre supprimer et nouveau. Il se peut que quelque chose se passe à l'arrière-plan que vous n'ayez jamais remarqué. En outre, la même valeur de pointeur peut ne pas correspondre à la même mémoire physique. Les pages de mémoire sont déplacées et recherchées. Un pointeur peut être mappé vers un emplacement totalement différent du précédent.

Conclusion: si vous n’avez pas initialisé spécifiquement un emplacement de mémoire, vous ne pouvez en déduire rien de son contenu. Le gestionnaire de mémoire peut même ne pas allouer un emplacement de mémoire physique spécifique avant que vous n'utilisiez la mémoire.

La gestion de la mémoire moderne est incroyablement complexe, mais en tant que programmeur C++, vous ne vous en souciez pas (principalement ‡). Respectez les règles et vous n'aurez pas de problèmes.

‡ Vous pouvez vous soucier d’optimiser pour réduire les erreurs de page.

4
Michael J

Ce n'est pas operator new, c'est l'opérateur new. Il y a en fait une grande différence! La différence est que operator new est une fonction qui renvoie la mémoire brute; lorsque vous utilisez l'opérateur new, il appelle un constructeur pour vous. C'est le constructeur qui définit la valeur de ce int, pas operator new.

3