おもに、オブジェクト指向プログラミングの機能を備えたプログラミング言語がもつ、演算子、あるいはキーワードの1つで、インスタンス(オブジェクト)を生成する役割を持ちます。
仕様はプログラミング言語による違いがありますが、多くの場合、ヒープ領域と呼ばれる場所から必要なメモリを確保し(ダイナミックメモリアロケーション)、そこにインスタンスを生成するという2段階の処理を行っています。ただし、C# で値型のインスタンスを生成する場合など、メモリの確保先がヒープ領域でない場合もあります(この例ではスタック領域を使う)。
また、インスタンスを確実に適切な状態に初期化するために、コンストラクタと呼ばれる機能を備えている言語が多いです。
このように、動的にメモリ確保を行ってインスタンスを生成する場合、そのインスタンスが不要になったときに解放の処理を行う必要があります。プログラミング言語によっては(フレームワークやライブラリが提供することもある)、不要になったことを検知して自動的に解放を行う機構が備わっていることがありますが(ガーベジコレクション)、そうした機構がない場合には、プログラマーが明示的に解放の処理を記述しなければなりません。すでに不要となっているのにもかかわらず、解放が行われずにプログラムの実行が続くことをメモリリークと呼び、いずれメモリを使い尽くしてしまい、プログラムが異常終了するなどの問題を引き起こす恐れがあります。
C++ では、new T(args)
のような new式と呼ばれる式の中で new演算子を用います。この場合、T型のオブジェクトが必要とするメモリを確保したのち、そこに T型のオブジェクトを生成し、生成されたオブジェクトを指し示すポインタを返します。したがって、T* instance = new T(args);
のような使い方になります。args
はコンストラクタに渡す実引数です。
メモリがどこから確保されるかに関して、C++ の標準規格は規定していませんが、一般的にはヒープ領域が使われると考えられます。
オブジェクトの配列を生成する場合には、要素数を指定できる new[] を使う必要があり(T* array = new T[128];
)、単一のオブジェクトを生成するための new と使い分けなければなりません。
new によって確保されたメモリ領域は動的ストレージ期間を持ち、delete instance;
のようなかたちで、delete演算子 による解放を行うまで存在し続けます。また、new[] で確保された配列の解放には delete[] を使う必要があります。
こうした明示的な解放が必要なうえに、delete と delete[] の使い分けにも注意しなければなりませんし、二重解放を避けなければならないことや、解放されたポインタを誤って使わないようにすることなど(ダングリングポインタ)、C++ のメモリ管理には多くの難しさがあります。スマートポインタのような仕組みにオブジェクトの管理を任せ、解放をデストラクタに行わせる手法(RAII)は重要です。
このほか、C++ では、new(new[] や delete、delete[] も含む)を演算子オーバーロードして、メモリを割り当てる方法をカスタマイズできる柔軟さがあります。
また、こうして定義した演算子関数に対して、追加の引数を渡す仕組みがあります。すでに確保できているメモリ領域を使って、特定のメモリアドレスにオブジェクトを生成する用途で用いることが多い機能であり、このことから、配置new(プレースメントnew)と呼ばれています。
Programming Place Plus のトップページへ
はてなブックマーク に保存 | Pocket に保存 | Facebook でシェア |
X で ポスト/フォロー | LINE で送る | noteで書く |
![]() |
管理者情報 | プライバシーポリシー |