48

このリファレンスによるとoperator new

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

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

operator newこれは、 (placement )の 3 番目のバージョンがnewC++ プログラムのすべての翻訳単位で暗黙的に宣言されているわけではなく、存在するためにヘッダー<new>を含める必要があることを暗示しているように思えます。あれは正しいですか?

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

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

// 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>ですか?

4

4 に答える 4

15

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

于 2010-05-07T12:32:33.533 に答える
15

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します。[注:暗黙の宣言では、、、、、、またはライブラリがこれらの名前を宣言するために使用するその他の名前は導入されません。したがって、ヘッダーを含めずにこれらの関数の1つを参照するnew-expression、delete-expression、またはfunction呼び出しは整形式です。ただし、、、を参照すると 、適切なヘッダーを含めて名前が宣言されていない限り、形式が正しくありません。—エンドノート]operator new[]operator deleteoperator delete[]stdstd::bad_allocstd::size_t<new>stdstd::bad_allocstd::size_t

また、のstd::nothrowバージョンでoperator newはヘッダーを含める必要があります()。

ただし、この標準では、他のヘッダーファイル内にヘッダーファイルを暗黙的に含めることは指定されていません。std::bad_allocそのため、名前などが参照される場合は、標準に従うことが安全でポータブルです。

于 2010-05-07T12:35:50.173 に答える
6

タイトルの質問についてですが、

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

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

本文中の質問については、

この例は、このインクルードなしで私にとってまったく同じようにコンパイルおよび実行されるようです?

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

于 2017-01-26T19:05:27.883 に答える
4

newヘッダーで定義された演算子は、メモリ割り当てが不可能な場合にNULLを返す代わりに、例外(同じヘッダーで宣言されている)を<new>スローします。ヘッダーも定義します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>ヘッダーで宣言されています。ただし、一部のコンパイラはそれらを暗黙的に使用可能にする場合がありますが、これは非標準であり、これに依存しないでください。

于 2010-05-07T12:20:35.190 に答える