3

小さな標準ヘッダー ファイルに出会いました<new>。おそらくこれまでに直接使用したことはありません。興味のある方はg++版をどうぞ

以下の部分は私の興味です:

  struct nothrow_t { };
  extern const nothrow_t nothrow;
  /** If you write your own error handler to be called by @c new, it must
   *  be of this type.  */
  typedef void (*new_handler)();
  /// Takes a replacement handler as the argument, returns the previous handler.
  new_handler set_new_handler(new_handler) throw();
  1. プログラマはどのようstruct nothrow_tにオブジェクトnothrowを使用しますか? オブジェクトは本当に必要externですか?
  2. はいつnew_handler使用されますか?
  3. すべてがblockoperator new/deleteで宣言されているのはなぜですか?extern C++
4

2 に答える 2

4

nothrow_toperator new下位互換性のある「例外をスローするのではなく、失敗時に null を返す」モードで動作するように指示するために使用されます。

つまり、次のようなコードが表示された場合:

int * idx = new(std::nothrow) int;

それは仕事中でしょうnothrow_t。標準の関連セクションについては、(C++11 N3376 以降) 17.6.4.6 [replacement.functions]/1 から開始し、そこから下に進んでください。

特定の質問に答えるには:

  1. はい、少なくとも 18.6 [support.dynamic]/1 によれば、extern である必要があります。これには以下が含まれます。

    namespace std {
        class bad_alloc;
        class bad_array_new_length;
        struct nothrow_t {};
        extern const nothrow_t nothrow;
        typedef void (*new_handler)();
        new_handler get_new_handler() noexcept;
        new_handler set_new_handler(new_handler new_p) noexcept;
    }
    

    さらに、17.6.2.3 [using.linkage]/1 には、「C++ 標準ライブラリのエンティティには外部リンケージ (3.5) があります」と記載されています。関数とクラス (上記get_new_handlerなどset_new_handler) は、デフォルトで外部リンケージを持つため、外部リンケージを持つために明示的に注釈を付ける必要はありません。

  2. new_handleroperator newユーザーがを呼び出して使用中のデフォルトをオーバーライドするときに使用されますset_new_handler。単なる関数ポインタ型です。

  3. おそらく、署名operator newが C で予約されていないためですextern "C++"。これらの関数に対して、名前マングリングやその他の C++ 固有の処理を実行できることをコンパイラに伝えます。このようにして、1 つの翻訳単位を C として、もう 1 つを C++ としてコンパイルし、それらを同じバイナリにリンクすることができます。C の世界の誰かがコンパイラのoperator new.
于 2012-11-22T05:28:33.833 に答える
2

まあ、これは本当に「ドキュメントを読んでください」という質問です。C++ に関する優れた入門書では、 について説明する必要がありnothrowます。たとえば、私が思い出したように、Bjarne の「The C++ Programming Language」はそうです。

とにかく、例外を nullpointer の結果に変換するために使用し、nothrow新しいハンドラーを使用して、失敗した割り当てを再試行する可能性があります。std::bad_alloc

実際問題として、この機能を使用するとき、および一般にグローバル配置 new を使用するときは、クラスから新しい配置を取得しないようにするために::、前に置くことを忘れないでください。new の配置は一般的に避けるべきであることを除いて (非常に低レベルの言語機能であるため)、技術的に意味がない場合でもこれを行います。良い習慣として。newnothrow


例:

#include <iostream>     // std::wcout, std::endl
#include <stdlib.h>     // EXIT_FAILURE, EXIT_SUCCESS
#include <new>          // std::nothrow
using namespace std;

int main()
{
    int* const p = ::new( std::nothrow ) int[0x7fffffff/sizeof(int)];
    if( !p )
    {
        cout << "Allocation failed!" << endl;
        return EXIT_FAILURE;
    }
    cout << "Alles success!" << endl;
    delete[] p;
    return EXIT_SUCCESS;
}

私のシステムでの出力:

[D:\開発\テスト]
>
割り当てに失敗しました。

[D:\開発\テスト]
> _

上記は32ビットプロセスを想定していることに注意してください:)

于 2012-11-22T05:21:01.300 に答える