八葉の日記

日々、感じたことをまとめる場として利用する

placement new(確保済みアドレスを指定する)について

placement newという通常のnewと異なるメモリアロケート方法があり、
通常のnewに比べて、以下の利点がある。
・メモリアロケートの時間が短縮される
・メモリアロケートの例外が発生しないように制御できる

■使い方
通常のnewと違い明示的にデストラクタを呼ぶ必要があります。

#include <cstdlib>
#include <cstdio>

#include <iostream>

class Sample
{
	char a[256];
};

int main()
{
	//①メモリアロケート
	char* p_memory = new char[1024];

	//②オブジェクトの初期化
	Sample* p = new(p_memory) Sample();

	//③オブジェクトの破壊
	p->~Sample();

	//④メモリ解放
	sth::operator delete(p, p);

	return 0;
}


最後に利点について補足します
・メモリアロケートの時間が短縮される
 通常newの処理はざっくりいうと、使用できるメモリを探す→オブジェクトへ割り当る→コンストラクタで初期化
 初めの、使用できるメモリを探す処理は結構ややこしく、メモリの断片化を防ぐために効率よくメモリ配置が行わ
 れるため、時間がかかります。

 確保済みアドレスを指定する場合は、①のメモリアロケートを事前に行うことで、
 その後の処理時間を短縮できます。 

・メモリアロケートの例外が発生しないように制御できる
 ①のメモリアロケートを事前に行い成功すると、②の処理で失敗することはない。
 (失敗する理由がない、また、C++14から例外投げないことが明示されたと思います)

 このことからシステム設計段階で各モジュールが利用できるメモリサイズを決めて置くと、
 以下のことができます。
 ・システム起動時にメモリ確保
  →普通成功する。万が一失敗した場合は、システム自体起動しない。
 ・実行中のnewの処理でplacement newを使用していると、実行時にエラーが
  発生しない。
  →メモリアロケート失敗時のめんどくさい例外処理を考えなくてよい

これを戦闘機のシステムのように実行時エラーが許されない(実行時エラー起こしたら墜落します)
ものに適用すると、リスクが減らせるから推奨されるようです。

確かF35から適用されたコーディングルールには適用されていたかと思う。
http://www.stroustrup.com/JSF-AV-rules.pdf