2014年4月7日月曜日

Dで配置new的なことをするメモ

D言語のGCを利用せずにクラスを扱いたいと思っていたので調べてみた。

C++だといわゆる配置new(Placement New)、自分で確保したメモリ領域にクラスのインスタンスを作ることができる。
D言語だとどう書けばいいのか。

クラスアロケータとか言う奴がある。クラス定義の中で、
new (uint size) {
...
}
と書いて、最後に自分のポインタを返せばいいらしい。しかしながら、"Note: Class allocators are deprecated in D2. "であるので、この方法は使わない。
じゃあ代替手段はと言うと、こういうのがある。
import std.stdio;
class C
{
this(string arg = "")
{
writeln("constructor is called." ~ arg);
}
~this()
{
writeln("destructor is called.");
}
}
T allocate(T, Args...)(Args args)
{
import std.conv : emplace;
import core.stdc.stdlib : malloc;
auto size = __traits(classInstanceSize, T);
auto memory = malloc(size)[0..size];
if(!memory)
{
import core.exception : onOutOfMemoryError;
onOutOfMemoryError();
}
return emplace!(T, Args)(memory, args);
}
void deallocate(T)(T obj)
{
import core.stdc.stdlib : free;
destroy(obj);
free(cast(void*)obj);
}
void main()
{
auto test = allocate!C("YEAH!");
scope (exit) deallocate(test);
}
view raw classAllocate.d hosted with ❤ by GitHub


__traitsでクラスインスタンスのサイズを取得して、mallocしてstd.convのemplaceでコンストラクタを呼び出せばいいようだ。
逆にdeallocateは、destroyしてから、クラスへのポインタをvoid*にcastして、freeに渡す。
C言語の機能はcore.stdc以下にあるようだ。
↑のコードではGCを利用するつもりが無いから元のコードにあるGC云々はしてないけど、これでGCを使わなくてもmallocでクラスを作れます。


0 件のコメント:

コメントを投稿