前のページ次のページ上に戻るホーム SophiaFramework UNIVERSE 5.3

11.4. 内部バッファ

文字列クラスは煩雑なバッファ(メモリ)管理をカプセル化してくれます。

11.4.1. C 言語文字列の取り出し

文字列クラス(SFXAnsiString / SFXWideString)は、 文字列を格納するための内部バッファを持ちます。

内部バッファの終端には自動的に '\0' が付加されます。

内部バッファのポインタを取得するための関数として、 SFXAnsiString::GetBuffer 関数と SFXAnsiString::GetCString 関数があります。 文字列が空である場合、これらの関数の振る舞いは以下のように異なります。

表 11.4. 内部バッファポインタ取得関数

関数名 解説 文字列が「空」である場合の振る舞い
SFXAnsiString::GetBuffer 文字列の内部バッファへのポインタを取得します。 null を返します。
SFXAnsiString::GetCString 文字列の内部バッファへの const ポインタを取得します。(内部バッファの内容を変更できません) '\0' へのポインタを返します。
[Note] 注意
文字列が空文字列のとき、SFXAnsiString::GetBuffer は null を、 SFXAnsiString::GetCString は '\0' を指すポインタを返します。

例 11.31. SFXAnsiString::GetBufferSFXAnsiString::GetCString の動作の違い

SFXAnsiString str;

// null を返すのでエラーが起こる
TRACE("%s", str.GetBuffer());

// '\0' を指すポインタを返すので正しく動作する
TRACE("%s", str.GetCString());

11.4.2. 複数の '\0' を含む文字列

文字列クラス(SFXAnsiString / SFXWideString)では、 複数の '\0' を含む文字列を扱えます。

以下の関数の動作は異なります。

表 11.5. 複数の '\0' を含む文字列処理関数の差異

関数名 解説
SFXAnsiString::GetLength 複数の '\0' を含む文字列の文字数を取得します。'\0' も文字数にカウントされます。
SFXAnsiString::GetLengthCString 最初の '\0' までの文字列の文字数を取得します。'\0' は文字数にカウントされません。
SFXAnsiString::IsEmpty '\0' を含めて文字列の文字数が 0 か判定します。先頭の文字が '\0' のとき、長さは 1 以上になるので false になります。
SFXAnsiString::IsEmptyCString 最初の '\0' までの文字列('\0' は含まない)の文字数が 0 か判定します。先頭の文字が '\0' のとき、true になります。

例 11.32. 複数の '\0' を含む文字列の処理

// 第 2 引数で文字列の長さを設定しない場合は "abc" だけが登録される
SFXAnsiString string("abc\0abc\0\0abc", 12);

SInt32 i = string.GetLength();          // i = 12
SInt32 j = string.GetLengthCString();   // j = 3

// nullstring1 は、文字を何も含まない長さ 0 の文字列
SFXAnsiString nullstring1;

Bool x = nullstring1.IsEmpty();         // x = true
Bool y = nullstring1.IsEmptyCString();  // y = true

// nullstring2 は、'\0' だけを含む文字列
SFXAnsiString nullstring2("\0", 1);

Bool x = nullstring2.IsEmpty();         // x = false
Bool y = nullstring2.IsEmptyCString();  // y = true

11.4.3. 内部バッファの委譲

Attach 関数は、引数に指定されたメモリを文字列オブジェクトの新しい内部バッファにする関数です。 Attach 関数実行後、このメモリの解放権は文字列オブジェクトが持ちます。

[Note] 注意
Attach 関数実行により、文字列オブジェクトの現在の内部バッファは破棄されます。

例 11.33. Attach 関数の使い方

SFXAnsiString string;
ACharPtr char_ptr;

char_ptr = static_cast<ACharPtr>(MemoryAllocate(10240)); // メモリを確保する

// char_ptr を使う処理

// char_ptr に確保したメモリを string オブジェクトに委譲する
string.Attach(char_ptr, 10240);

// char_ptr を明示的に解放してはいけない

// Attach 関数を使わない場合
// string.Set(char_ptr, 10240); // char_ptr の中身がコピーされるので、スピードは遅くなることに注意が必要
[Note] 注意
string オブジェクトに委譲した char_ptr のメモリは、 MemoryFree 関数を呼び出して解放してはいけません。 メモリの解放権は、string オブジェクトが持ちます。

Detach 関数は、文字列オブジェクトの現在の内部バッファを返す関数です。 返されたメモリ領域の解放権は、返された側が持ちます。

例 11.34. Detach 関数の使い方

SFXAnsiString string;
ACharPtr char_ptr;
SInt32 length;

string = "The best application for BREW.";

// string を使う処理

// string オブジェクトの内部バッファの解放権を char_ptr に渡す
char_ptr = string.Detach(&length);

// char_ptr のサイズを表示する
TRACE("%d", length);

// char_ptr を使う処理

// 必ず char_ptr を解放する
MemoryFree(char_ptr);
[Note] 注意
string オブジェクトから返却された char_ptr のメモリは、 明示的に MemoryFree 関数を呼び出して解放しなければいけません。 メモリの解放権は、char_ptr オブジェクトが持ちます。
[Note] 注意
Attach 関数と Detach 関数は、互いに逆の操作を行います。