ホーム < ゲームつくろー! < ツール編


その9 メモリブロッククラス(v1.01)


 色々な型のデータをシーケンシャルにメモリに格納していくクラスです。

名前 バージョン 公開日
メモリブロック 1.01 2010. 1.9

バージョンレポートはこちら

 モデルデータやビットマップの絵の情報など、沢山の値が連続で並ぶ情報は一塊で扱えると便利です。メモリブロッククラスはそういう様々なデータを連続的に(シーケンシャル)にメモリに格納していきます。扱い方は非常にシンプルです。データを格納するには左シフト(<<)演算子を用います。データにアクセスするには配列([ ])演算子を用います。詳しい使い方は後述のコードをご覧下さい。

 このクラスは内部でスマートポインタ(dixsmartptr.h)を使用しています。dixsmartptr.hが同じフォルダ内に無いとコンパイルエラーになりますのでご注意ください。


○ 定義

名前空間 ヘッダー
Dix MemBlock.h


○ メモリブロッククラスメンバメソッド

公開メンバメソッド 説明 使い方 備考
MemBlock()
コンストラクタ MemBlock mb; コンストラクタではmallocによる空メモリの確保が行われます。
~MemBlock( void ) デストラクタ - -
unsigned size() 格納サイズを取得 MemBlock mb;
mb << 100;
unsigned sz = mb.size()
格納されたメモリブロックのサイズを取得します。
MemBlock& push( const void *src, unsigned data ) データを追加 MemBlock mb;
mb.push( "Test", 5 );
メモリブロックの最後尾に指定サイズだけデータを追加します。


演算子 説明 使い方 備考
const char &operator []( int e ) const データにアクセス MemBlock mb;
mb << "ABCDE";
const char str = mb[3];  // C
格納されているデータにアクセスします。データの先頭ポインタを得るにはこの演算子を通し、
const char *ptr = &mb[0];
として下さい。
MemBlock &operator <<( const char* str );
MemBlock &operator <<( const MemBlock &src );
template< class T> MemBlock &operator <<( const T &src );
データを追加 MemBlock mb;
mb << 100 << "Test" << 12.345f;
MemBlock mb2;
mb2 << mb1 << "End";
メモリブロックの最後尾にデータを追加します。戻り値はMemBlockなので使い方にあるように<<演算子を連続して適用できます。
文字列は終端文字が含まれます。
テンプレート定義がされているので型固定(サイズ固定)のデータであれば構造体でも何でも格納できます。


○ バージョンレポート

v1.00 -> 1.01(2010. 1. 9)
・ pushメソッド追加

v1.00 (2010. 1. 8)
・ 初出実装

○ 使い方

#include "stdafx.h"
#include "memblock.h"

struct MYDATA {
    int a;
    float b;
    double c;
    char str[7];

    MYDATA() : a(100), b(200.0f), c(300.456) {
        memcpy( str, "MyData", 7 );
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    Dix::MemBlock mb;
    mb << "This is a Test !\n";
    printf( &mb[0] );

    // 保存テスト
    Dix::MemBlock mb3;
    MYDATA myData;
    myData.a = 9999;
    myData.b = 8888.8f;
    myData.c = 777.777;
    memcpy( &myData.str, "<Text>", 7 );
    mb3 << myData; // 保存

    // 読み込みテスト
    MYDATA loadData;
    memcpy( &loadData, &mb3[0], sizeof(MYDATA) ); // 読み込み

    printf("%d, %f, %f, %s", loadData.a, loadData.b, loadData.c, loadData.str );
    printf("\n");

    return 0;
}

 コードにあるように左シフト演算子でメモリブロックに格納します。

 コピーについて、このクラスはメモリブロックへのポインタをスマートポインタで包んでいます。よって代入演算子や関数に渡す場合にはポインタの共有が行われ、メモリのハードコピーは行われません。関数の引数にする場合は実体渡しでも特に問題ありませんが、可能であればアドレス渡しをした方が効率的です:

// 実体渡し
void func( MemBlock block ) {
   block << "Data" << 12345;
}

// アドレス渡し
// こちらの方が内部でスマートポインタの参照カウンタに使うnewが発生しない分効率的です
void func2( MemBlock &block ) {
   block << "Data" << 12345;
}