C++のplacement new(配置new)演算子とは?仕組みと使い方を解説
この記事では、C++における「placement new(配置new)」演算子について詳しく解説します。placement newは、通常のnew演算子のバリエーションのひとつです。
通常のnew演算子との違い
まず、通常のnew演算子は次の2つの処理を行います。
- メモリを割り当てる
- 割り当てたメモリ上にオブジェクトを構築する
通常のnew演算子はヒープ領域にメモリを確保し、そこにオブジェクトを構築します。これに対してplacement newは、プログラマが指定したアドレス上に直接オブジェクトを構築するという点が大きく異なります。メモリの新規確保は行いません。
また、new演算子で確保したメモリはdeleteキーワードで解放できますが、placement newには対応する「placement delete」という機能が存在しないことにも注意が必要です。placement newで構築したオブジェクトを破棄する場合は、明示的にデストラクタを呼び出す必要があります。
placement newのメリットと構文
placement newを使うと、すでに変数に割り当てられているメモリ上にオブジェクトを「構築」できます。新たなメモリ割り当てを行わずに既存のメモリを再利用できるため、再割り当てのコストを削減でき、パフォーマンス最適化の観点から非常に有用です。
構文は以下のとおりです。
new (address) (type) initializer
addressには、指定した型の新しいオブジェクトを構築したいメモリアドレスを指定します。
サンプルコード
#include<iostream>
using namespace std;
int main() {
int a = 5;
cout << "a = " << a << endl;
cout << "&a = " << &a << endl;
// placement newによってaの値を10に変更する
int *m = new (&a) int(10);
cout << "\nplacement new使用後:" << endl;
cout << "a = " << a << endl;
cout << "m = " << m << endl;
cout << "&a = " << &a << endl;
return 0;
}
実行結果
a = 5 &a = 0x22fe34 placement new使用後: a = 10 m = 0x22fe34 &a = 0x22fe34
コードの解説
この例では、変数aのアドレス(&a)に対してplacement newを使用しています。実行結果を見ると、ポインタmはaと同じアドレス(0x22fe34)を指しており、そのメモリ上の値が10に書き換えられていることがわかります。
つまり、新しいメモリを確保することなく、既存の変数aのメモリ領域をそのまま再利用して新しい値を設定できているのです。これがplacement newの基本的な動作です。
まとめ
- 通常のnew:メモリ確保+オブジェクト構築(ヒープ領域に割り当て)
- placement new:指定アドレスへのオブジェクト構築のみ(メモリ確保なし)
- placement deleteは存在しないため、破棄時は明示的なデストラクタ呼び出しが必要
- メモリ再利用による高速化など、最適化目的で活用できる
-
C++のアロー演算子(矢印演算子)とは?ドット演算子との違いをわかりやすく解説
C++には、クラスのメンバーにアクセスするための演算子として「ドット演算子(.)」と「アロー演算子(->)」の2種類があります。どちらも同じ目的で使われますが、使用する場面が異なります。C++では、class、struct、unionとして宣言された型はすべて「クラスタイプ」とみなされます。以下の説明は、これらすべてに共通して当てはまります。ドット演算子とアロー演算子の基本的な違いa.b は、b がオブジェクトa(またはオブジェクトへの参照)のメンバーである場合にのみ使用できます。つまり、a.b の形式では、a は必ず実際のオブジェクト(またはオブジェクトへの参照)になります。a->
-
C++の単項演算子とは?種類・使い方を実例付きで解説
単項演算子(unary operator)とは、1つのオペランド(被演算子)に対して作用し、新しい値を生成する演算子のことです。C++には以下のような単項演算子が用意されています。 C++の主な単項演算子一覧 演算子説明 間接参照演算子(*)ポインタ変数に作用し、そのポインタが指すアドレスにある値に相当するlvalueを返します。この操作はポインタの「デリファレンス(間接参照)」と呼ばれます。 アドレス取得演算子(&)オペランドのメモリアドレスを取得する単項演算子です。オペランドとしては、関数指定子、またはビットフィールドでなく、register記憶クラス指定子を付けずに宣言さ