私はnewとdeleteをオーバーロードしました。本で読んでいたのですが、 newとmallocの違いはnewがコンストラクターを呼び出し、呼び出し元の変数の型を返すことであり、3 つ目の違いはクラスごとにnewをオーバーロードできることです。 mallocはできませんが、誰かがこのクラスをクラスごとに説明できますか。
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 );
これはたまたま呼び出された新しい関数ですmalloc
。std::
ただし、明示的な修飾を使用してライブラリ関数を呼び出す方が適切であり、std::malloc
オーバーロードを追加することはライブラリの規則に反します。
を置き換えることはできませんstd::malloc
。置き換えることができる唯一の関数は、 の標準バリアントです::operator new
。malloc
返されたメモリ ブロックに入るクラスを示す引数を取らないため、クラス固有のものはありません。malloc
返されたメモリで何をするかわかりません。それは単なるバイトの塊です。
プログラムの編成の問題として、より特化したアロケーターを別の名前で指定して呼び出す必要がありmalloc
ます。タイプに応じて異なる関数を呼び出す必要がある場合は、テンプレートを使用します。
template< typename allocated >
void *my_allocate( std::size_t sz ); // maybe "sz" param is unnecessary.
また、specializestd::allocator< my_class >
とそのメンバー関数を使用することもできますallocate
。次に、さまざまな標準ライブラリ機能が、カスタマイズされていないにもかかわらず、関数を呼び出しますnew
。new
(癖があるため、カスタムに深く入り込むのは避けるかもしれません。)
注意:標準 C ライブラリ関数を自由に「オーバーロード」または「上書き」することはできませんが、その適切なサブセットをオーバーライドできるようにするのが一般的な方法です。
一般に、リンカは指定されたオブジェクト ファイルがどの言語で記述されたかを認識せず、非常に低いレベルの知識で動作します。オブジェクト ファイルの外部シンボルは、リンクされているすべてのオブジェクト ファイルと共有ライブラリの中で一意である必要があります。リンカー自体は、コマンドラインで指定された重複シンボルを含むオブジェクトを自由に削除できないためです。注目すべき例外はスタティック ライブラリ (.a) です。リンカーは、重複する外部シンボルを削除するのに役立つ場合、アーカイブから任意のアイテムを削除できます。
ライブラリ関数をオーバーライドする許可は、次の 2 つの部分で構成されます。
関数をオーバーロード可能としてマークする構文を持つコンパイラ-適切な外部シンボルは「弱いリンケージ」としてマークされます。Fe の場合
gcc
:`__attribute__((weak)) void *malloc(size_t size)`
ld.so
弱いリンケージを理解する動的リンカー( )。
malloc()
特定の shared で が弱いシンボルとして宣言されているかどうかは不明ですがlibc
、一般的には宣言されているため、オーバーライドできる可能性が高くなりますが、マイレージは異なる場合があります。
はい、標準ライブラリ関数 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 のような標準ライブラリ関数をオーバーロードできます。