module pind.samples.ja.memory.memory_2; import core.memory; /* GC.reallocと同じように動作するが、メモリが拡張された場合、 * 余分なバイトをクリアする。 */ void * reallocCleared( void * buffer, size_t oldLength, size_t newLength, GC.BlkAttr blockAttributes = GC.BlkAttr.NONE, const TypeInfo typeInfo = null) { /* 実際の処理をGC.reallocに委譲する。 */ buffer = GC.realloc(buffer, newLength, blockAttributes, typeInfo); /* 拡張された場合、余分なバイトをクリアする。 */ if (newLength > oldLength) { import core.stdc.string; auto extendedPart = buffer + oldLength; const extendedLength = newLength - oldLength; memset(extendedPart, 0, extendedLength); } return buffer; } struct Array(T) { T * buffer; // 要素を格納するメモリ領域 size_t capacity; // バッファの要素容量 size_t length; // 実際の要素数 /* 指定した要素を返す */ T element(size_t index) { import std.string; enforce(index < length, format("Invalid index %s", index)); return *(buffer + index); } /* 要素を末尾に追加する */ void append(T element) { writefln("Appending element %s", length); if (length == capacity) { /* 新しい要素を格納するスペースがない; そのため、 * 容量を増やす必要がある。 */ size_t newCapacity = capacity + (capacity / 2) + 1; increaseCapacity(newCapacity); } /* 要素を末尾に配置する */ *(buffer + length) = element; ++length; } void increaseCapacity(size_t newCapacity) { writefln("Increasing capacity from %s to %s", capacity, newCapacity); size_t oldBufferSize = capacity * T.sizeof; size_t newBufferSize = newCapacity * T.sizeof; /* また、このメモリブロックをポインタの検索対象から * 除外するように指定する。 */ buffer = cast(T*)reallocCleared( buffer, oldBufferSize, newBufferSize, GC.BlkAttr.NO_SCAN); capacity = newCapacity; } } import std.stdio; import core.memory; import std.exception; // ... void main() { auto array = Array!double(); const count = 10; foreach (i; 0 .. count) { double elementValue = i * 1.1; array.append(elementValue); } writeln("The elements:"); foreach (i; 0 .. count) { write(array.element(i), ' '); } writeln(); }