web-dev-qa-db-ja.com

C ++で#include <new>ライブラリはいつ必要ですか?

演算子newのこの参照エントリによると( http://www.cplusplus.com/reference/std/new/operator%20new/ ):

グローバル動的ストレージ演算子関数は、標準ライブラリでは特別です。

  • Operator newの3つのバージョンはすべて、std名前空間ではなく、グローバル名前空間で宣言されています。
  • 最初のバージョンと2番目のバージョンは、C++プログラムのすべての変換単位で暗黙的に宣言されています。ヘッダーを含めるために、ヘッダーを含める必要はありません。

これは、C++プログラムのすべての変換ユニットで演算子new(プレースメントnew)の3番目のバージョンが暗黙的に宣言されておらず、ヘッダー<new>が含まれる必要があることを示唆しているように思われます。あれは正しいですか?

もしそうなら、g ++とMS VC++ Expressの両方のコンパイラを使用すると、ソースコードに#include <new>なしでnewの3番目のバージョンを使用してコードをコンパイルできるように見えるのはどうしてですか。

また、operator newのMSDN標準C++ライブラリリファレンスエントリは、#include <new>ステートメントを含むoperator newの3つの形式のコード例をいくつか示していますが、このインクルードは、このインクルードなしでコンパイルおよび実行されているようです。

// 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;
}

誰かがこれについていくつかの光を当てることができますか?いつ、なぜ#include <new>-#include <new>なしではコンパイルできないいくつかのサンプルコードが必要になる可能性がありますか?

ありがとう。

44
Paul Caheny

C++では、標準ヘッダーに他の標準ヘッダーを含めることを妨げるものはありません。したがって、any標準ヘッダーを含める場合、間接的にallを含めることが考えられます。ただし、この動作は完全に実装に依存するため、特定のヘッダーの機能が必要な場合は、常に明示的に自分で含める必要があります。

11
anon

C++標準の詩3.7.4.2は言う:-

ライブラリは、グローバル割り当て関数と割り当て解除関数のデフォルトの定義を提供します。一部のグローバル割り当ておよび割り当て解除関数は置き換え可能です(18.6.1)。 C++プログラムは、置き換え可能な割り当て関数または割り当て解除関数の最大1つの定義を提供します。このような関数定義は、ライブラリで提供されているデフォルトのバージョン(17.6.3.6)を置き換えます。次の割り当て関数と割り当て解除関数(18.6)は、プログラムの各変換単位のグローバルスコープで暗黙的に宣言されています。

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();

これらの暗黙の宣言では、関数名operator new、operator new []、operator delete、operator delete []のみが導入されています。 [注:暗黙の宣言では、std、std :: bad_alloc、およびstd :: size_tという名前、またはライブラリがこれらの名前を宣言するために使用するその他の名前を紹介していません。したがって、ヘッダーを含めずにこれらの関数の1つを参照するnewexpression、delete-expression、または関数呼び出しは整形式です。ただし、std、std :: bad_alloc、およびstd :: size_tの参照は、適切なヘッダーを含めることによって名前が宣言されていない限り、形式が正しくありません。 -エンドノート]

また、std::nothrowバージョンoperator newにはヘッダーを含める必要があります。ただし、標準では、他のヘッダーファイル内にヘッダーファイルを暗黙的に含めることは指定されていません。したがって、名前がstd::bad_allocなどを参照。

14
Abhay

タイトルの質問については、

C++で#include <new>ライブラリが必要になるのはいつですか?

キーワードnewはさまざまな方法で使用できます。通常の使用では、ヘッダーを含める必要はありません。ただし、このキーワードを使用する1つの可能な方法は、<new>ヘッダーで定義された特定の「placement new」関数を呼び出すことです。その使用法では、<new>ヘッダーを直接または間接的に含める必要があります。必要でない限り、そのヘッダーやその他のヘッダーを含めないでください。デフォルトではヘッダーを含めないでください。一方、別のヘッダーを含むヘッダーの実装固有のバージョンに依存しないでください。常に、標準の(またはその他の)仕様に従って必要なものを含めてください。

本文の質問に関しては、

このインクルードなしで、例のコンパイルと実行は同じです。

C++では、実装の裁量で、標準ライブラリヘッダーに他の標準ライブラリヘッダー(または他の標準ライブラリヘッダーによって提供されるもの)を含めることが許可されています。

<new>ヘッダーで定義された演算子newは、メモリ割り当てができない場合にNULLを返す代わりに、bad_alloc例外(同じヘッダーで宣言されています)をスローします。 <new>ヘッダーも定義します

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

例外をスローしないバリアントと配置の新しいバリアント。 <new>がないと、プレーンな古い、NULLを返すoperator newのみが取得されます。。 3つすべての演算子のオーバーロード:

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();

<new>ヘッダーで宣言されています。ただし、一部のコンパイラーは暗黙的にそれらを使用可能にする場合がありますが、これは非標準であり、それに依存するべきではありません。

3
el.pescado