2

私はnewdeleteをオーバーロードしました。本で読んでいたのですが、 newmallocの違いはnewがコンストラクターを呼び出し、呼び出し元の変数の型を返すことであり、3 つ目の違いはクラスごとにnewをオーバーロードできることです。 mallocはできませんが、誰かがこのクラスをクラスごとに説明できますか。

4

4 に答える 4

4

::operator newグローバル名前空間では、オーバーロードではなく、置換 (オーバーライド) できます。これにより、標準ライブラリが提供する関数の代わりにオーバーライドが使用されます。Andmy_class::operator newを指定できるので、new my_class式で使用されます。これもオーバーロードとは異なります。

オーバーロードは、配置構文newを使用する場合にのみ機能します。new

new ( memory_pool, 123, other_args ) my_class( constructor_args )

newキーワードの後に​​括弧内に追加の引数を指定すると、別のオーバーロードが呼び出され、必要なメモリ量を指定しoperator newた後に追加の引数が追加されます。size_t

::malloc異なる引数を取るバージョンを定義することで、他の関数と同じようにオーバーロードできます:

void *malloc( std::size_t size, allocation_pool &pool );

これはたまたま呼び出された新しい関数ですmallocstd::ただし、明示的な修飾を使用してライブラリ関数を呼び出す方が適切であり、std::mallocオーバーロードを追加することはライブラリの規則に反します。

を置き換えることはできませんstd::malloc。置き換えることができる唯一の関数は、 の標準バリアントです::operator newmalloc返されたメモリ ブロックに入るクラスを示す引数を取らないため、クラス固有のものはありません。malloc返されたメモリで何をするかわかりません。それは単なるバイトの塊です。

プログラムの編成の問題として、より特化したアロケーターを別の名前で指定して呼び出す必要がありmallocます。タイプに応じて異なる関数を呼び出す必要がある場合は、テンプレートを使用します。

template< typename allocated >
void *my_allocate( std::size_t sz ); // maybe "sz" param is unnecessary.

また、specializestd::allocator< my_class >とそのメンバー関数を使用することもできますallocate。次に、さまざまな標準ライブラリ機能が、カスタマイズされていないにもかかわらず、関数を呼び出しますnewnew(癖があるため、カスタムに深く入り込むのは避けるかもしれません。)

于 2013-04-29T05:08:42.110 に答える
1

注意:標準 C ライブラリ関数を自由に「オーバーロード」または「上書き」することはできませんが、その適切なサブセットをオーバーライドできるようにするのが一般的な方法です。

一般に、リンカは指定されたオブジェクト ファイルがどの言語で記述されたかを認識せず、非常に低いレベルの知識で動作します。オブジェクト ファイルの外部シンボルは、リンクされているすべてのオブジェクト ファイルと共有ライブラリの中で一意である必要があります。リンカー自体は、コマンドラインで指定された重複シンボルを含むオブジェクトを自由に削除できないためです。注目すべき例外はスタティック ライブラリ (.a) です。リンカーは、重複する外部シンボルを削除するのに役立つ場合、アーカイブから任意のアイテムを削除できます。

ライブラリ関数をオーバーライドする許可は、次の 2 つの部分で構成されます。

  1. 関数をオーバーロード可能としてマークする構文を持つコンパイラ-適切な外部シンボルは「弱いリンケージ」としてマークされます。Fe の場合gcc:

    `__attribute__((weak)) void *malloc(size_t size)`
    
  2. ld.so弱いリンケージを理解する動的リンカー( )。

malloc()特定の shared で が弱いシンボルとして宣言されているかどうかは不明ですがlibc、一般的には宣言されているため、オーバーライドできる可能性が高くなりますが、マイレージは異なる場合があります。

于 2021-10-17T13:32:59.963 に答える
0

はい、標準ライブラリ関数 malloc をオーバーロードできます。以下のコード スニペットをご覧ください。

    #include <iostream>
    void malloc(void)
    {
        puts("malloc");
    }

    int main()
    {
        int *p= (int*)malloc(8);
        malloc();
        free(p);
        return 0;
    }

このコードはmallocを出力します。

また、以下は、このプログラムのメモリの TEXT セクションのスニペットです。

    0000000000400744 T _Z6mallocv
    0000000000400770 T main

以下はDYNAMIC SYMBOL TABLEのスニペットです

    0000000000000000      DF *UND*  00000000000001d2  GLIBC_2.2.5 malloc
    0000000000000000      DF *UND*  00000000000001a5  GLIBC_2.2.5 __libc_start_main

したがって、C++ の malloc のような標準ライブラリ関数をオーバーロードできます。

于 2015-03-23T15:19:01.593 に答える