2016-01-19 13 views
5

#include <new>(このエラーはis defined in the <new> headerであるため)がないにもかかわらず、プログラム内のnew式がbad_allocというエラーをスローする可能性がありますか?<new>ヘッダーが定義されていませんが、新しいthrow bad_alloc?

から3.7.4。 N3337:

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

void* operator new(std::size_t); 

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

void operator delete(void*); 

void operator delete[](void*); 

これらの暗黙の宣言は、関数名のみoperator newoperator new[]operator delete、およびoperator delete[]をご紹介します。 [注:暗黙の宣言では、stdstd::size_t、またはこれらの名前を宣言するためにライブラリが使用する他の名前はありません。したがって、ヘッダ<new>を含まないこれらの関数の1つを参照する新しい式 delete-expressionまたは関数呼び出しは形式の整ったものです。しかし、stdまたはstd::size_tを参照すると、適切なヘッダーを含めることによって名前が宣言されていない限り、正しく構成されません。 -end note]割り当ておよび/または割り当て解除関数も宣言し、任意のクラスに対して定義することができます

これはまだ私には分かりません。暗黙の宣言はstd::size_tを使用しますが、それらを導入しません(bad_allocの場合も同じです)。 std::size_tは、new式を使用する前に導入する必要はありませんか?これはどういう意味ですか、それとも額面でそれを取らなければなりませんか?

+1

さて、あなたは ''を含む標準C++ライブラリにリンクしているので、 'std :: bad_alloc'について知っています。 –

+0

C++の標準ヘッダーに他のC++標準ヘッダーを含めることは正式に許可されているという事実と関係しているかもしれませんが、これらの機能に関する限り、それはすべての話ではないと思います。 –

+0

いくつかの実験の後、私はこれが事実であると結論づけます。私はそれについての答えを書くつもりです。 –

答えて

4

あなたの引用は、これらのグローバル関数が存在し、説明するように暗黙的に宣言されていることを述べています。したがって、newを呼び出すと、標準ライブラリのグローバル関数が呼び出されます。グローバル関数newの実装はstd::bad_allocを投げるものであり、その実装はコンパイル時に<new>にアクセスしていたので、std::bad_allocを投げる方法を知っています。あなたのコードは、あなたがそれを捕まえようとしていない限り、std::bad_allocが何であるかを知る必要はありません。しかし、それをキャッチする以外に、これは、あなたが任意の例外をスローしているかもしれない他のライブラリから他の関数​​を呼び出すようなものです。あなたはそれをキャッチしようとしていない限り、例外の詳細を知る必要はありませんが、呼び出し側がそれを投げることを止めるわけではありません。

+0

私は、標準ライブラリから来るプログラムで使用するものは、 '#include'ヘッダを持たなければならないと思っていましたか?したがって、 'new'と' delete'関数のこれらの定義を見つけるために標準ライブラリに暗黙的にアクセスできますか? 'int main(){}'のような最低限のプログラムでさえ、標準ライブラリにアクセスする必要がありますか? – SergeantPenguin

+0

@SergeantPenguinもう少しニッキーニピキを得るために、 'new'と言うと、標準ライブラリを直接呼び出すことはありません。 'new'は言語のことです。 'new'を実行する行のどこかに、言語は、オブジェクトが常駐する実際のメモリを取得するためにグローバル割り当て関数を呼び出すでしょう(おそらくまもなくメモリのオブジェクトのコンストラクタを呼び出す言語が続きます) 。標準ライブラリは、あなたが自分で書く必要がないように、デフォルトのグローバル割り当て関数(指定された関数シグネチャを持つリンカがそれを見つけることができるように)を提供します。 –

4

名前std::size_tは、おそらくunsigned longまたはunsigned long longのような他の整数型のtypedefです。コンパイラは、size_tが表示されていない場合でも、newの実パラメータ型を認識します。

bad_allocと同様です。 bad_allocを投げるランタイムコードには、プログラムがなくても、確かに<new>ヘッダーが含まれています。

3

C++標準ヘッダーには、他のC++ヘッダーを含めることができます。したがって、を含まずにstd::bad_allocへの実装依存のアクセスを得ることができ、<cstddef>などを含むstd::size_tにアクセスすることができます。私は標準の版でそれを調べるのは面倒ですが、N4296ドラフトでは§17.6.5.2にあります。

C++ヘッダーには他のC++ヘッダーが含まれることがあります。

これはコンパイラで試すことができます。

int main() 
{ 
    std::size_t x; // error 
    std::bad_alloc y; // error 
} 

今度は完全に無関係な#includeを追加してみましょう。

#include <complex> 

int main() 
{ 
    std::size_t x; // probably not an error anymore, depends on compiler 
    std::bad_alloc y; // probably not an error anymore, depends on compiler 
} 
関連する問題