web-dev-qa-db-fra.com

Quand la bibliothèque #include <new> est-elle requise en C ++?

Selon cette entrée de référence pour l'opérateur new ( http://www.cplusplus.com/reference/std/new/operator%20new/ ):

Les fonctions globales de l'opérateur de stockage dynamique sont spéciales dans la bibliothèque standard:

  • Les trois versions de l'opérateur new sont déclarées dans l'espace de noms global, et non dans l'espace de noms std.
  • Les première et deuxième versions sont implicitement déclarées dans chaque unité de traduction d'un programme C++: il n'est pas nécessaire d'inclure l'en-tête pour qu'elles soient présentes.

Cela me semble impliquer que la troisième version de l'opérateur new (placement new) n'est pas implicitement déclarée dans chaque unité de traduction d'un programme C++ et dans l'en-tête <new> doit être inclus pour qu'il soit présent. Est-ce exact?

Si c'est le cas, comment se fait-il qu'en utilisant à la fois les compilateurs g ++ et MS VC++ Express, il semble que je puisse compiler du code en utilisant la troisième version de new sans #include <new> dans mon code source?

De plus, l'entrée de référence de la bibliothèque MSDN Standard C++ sur operator new donne un exemple de code pour les trois formes d'opérateur new qui contient le #include <new>, cependant l'exemple semble se compiler et s'exécuter exactement de la même manière pour moi sans cette inclusion?

// new_op_new.cpp
// compile with: /EHsc
#include<new>
#include<iostream>

using namespace std;

class MyClass 
{
public: 
   MyClass( )
   {
      cout << "Construction MyClass." << this << endl;
   };

   ~MyClass( )
   {
      imember = 0; cout << "Destructing MyClass." << this << endl;
   };
   int imember;
};

int main( ) 
{
   // The first form of new delete
   MyClass* fPtr = new MyClass;
   delete fPtr;

   // The second form of new delete
   char x[sizeof( MyClass )];
   MyClass* fPtr2 = new( &x[0] ) MyClass;
   fPtr2 -> ~MyClass();
   cout << "The address of x[0] is : " << ( void* )&x[0] << endl;

   // The third form of new delete
   MyClass* fPtr3 = new( nothrow ) MyClass;
   delete fPtr3;
}

Quelqu'un pourrait-il nous éclairer là-dessus et quand et pourquoi vous pourriez avoir besoin de #include <new> - peut-être un exemple de code qui ne se compilera pas sans #include <new>?

Merci.

44
Paul Caheny

Rien en C++ n'empêche les en-têtes standard d'inclure d'autres en-têtes standard. Donc, si vous incluez tout en-tête standard, vous pouvez éventuellement inclure indirectement tous d'entre eux. Cependant, ce comportement dépend totalement de l'implémentation, et si vous avez besoin des fonctionnalités d'un en-tête spécifique, vous devez toujours l'inclure explicitement vous-même.

11
anon

Le verset C++ Standard 3.7.4.2 dit: -

La bibliothèque fournit des définitions par défaut pour les fonctions globales d'allocation et de désallocation. Certaines fonctions globales d'allocation et de désallocation sont remplaçables (18.6.1). Un programme C++ doit fournir au plus une définition d'une fonction d'allocation ou de désallocation remplaçable. Une telle définition de fonction remplace la version par défaut fournie dans la bibliothèque (17.6.3.6). Les fonctions d'allocation et de désallocation suivantes (18.6) sont implicitement déclarées de portée globale dans chaque unité de traduction d'un programme.

void* operator new(std::size_t) throw(std::bad_alloc); 
void* operator new[](std::size_t) throw std::bad_alloc); 
void operator delete(void*) throw(); 
void operator delete[](void*) throw();

Ces déclarations implicites n'introduisent que les noms de fonction operator new, operator new [], operator delete, operator delete []. [Remarque: les déclarations implicites n'introduisent pas les noms std, std :: bad_alloc et std :: size_t ou tout autre nom utilisé par la bibliothèque pour déclarer ces noms. Ainsi, une nouvelle expression, suppression-expression ou appel de fonction qui fait référence à l'une de ces fonctions sans inclure l'en-tête est bien formé. Cependant, en référence à std, std: : bad_alloc, et std :: size_t est mal formé à moins que le nom n'ait été déclaré en incluant l'en-tête approprié. —fin note]

Également std::nothrow version du operator new nécessite l'inclusion de l'en-tête. La norme ne spécifie cependant pas l'inclusion implicite des fichiers d'en-tête dans les autres fichiers d'en-tête. Il est donc sûr et portable de suivre la norme lorsque les noms std::bad_alloc etc sont référés.

14
Abhay

Concernant la question dans le titre,

Quand est #include <new> bibliothèque requise en C++?

Le mot clé new peut être utilisé de différentes manières. L'utilisation ordinaire ne nécessite pas l'inclusion d'en-têtes. Mais une façon possible d'utiliser ce mot-clé est d'invoquer la fonction particulière "placement new" définie par le <new> entête. Avec cette utilisation, vous devez inclure directement ou indirectement le <new> entête. N'incluez pas cet en-tête ou tout autre en-tête, sauf si vous en avez besoin; n'inclut pas d'en-têtes par défaut. D'un autre côté, ne vous fiez pas à une version spécifique à l'implémentation d'un en-tête, y compris un autre: incluez toujours ce dont vous avez besoin selon les spécifications standard (ou autres) de ce qu'ils fournissent.

Concernant la question dans le corps,

l'exemple semble se compiler et fonctionner exactement de la même manière pour moi sans cette inclusion?

En C++, les en-têtes de bibliothèque standard sont autorisés à inclure d'autres en-têtes de bibliothèque standard (ou les éléments fournis par d'autres en-têtes de bibliothèque standard), à la discrétion de l'implémentation.

6

Opérateur new défini dans <new> l'en-tête lance bad_alloc exception (qui est déclarée dans le même en-tête) au lieu de retourner NULL lorsque l'allocation de mémoire n'est pas possible. <new> l'en-tête définit également

void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw();

variante qui ne lève pas d'exceptions et placement nouvelle variante. Sans pour autant <new> vous n'obtenez que du vieux simple, renvoyant NULL operator new. Surcharges des trois opérateurs:

void* operator new (std::size_t size) throw (std::bad_alloc);
void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw();
void* operator new (std::size_t size, void* ptr) throw();

sont déclarés dans <new> entête. Cependant, certains compilateurs peuvent les rendre disponibles implicitement, mais ce n'est pas standard et vous ne devez pas vous y fier.

3
el.pescado