vectorで表現するstring。

vectorで表現するstringを、vstringと呼んでみるテスト。

typedef std::vector<char> vstring;

コレで何がしたいのかと言うと、C文字列を表現したいのです。
ヌル文字で終端するアレ。


何故かと言えばやっぱり、可変長配列だから。
ほとんどの(凡人)プログラマがstringを使う理由はコレだと思うのです。
後はまぁ自分でnew/delete書かなくてイイとか。


以下vstringについてだらだらと。

文字列操作関数にバッファサイズ指定が要らなくなる。

//// キーワードを置換する関数。

// char配列版
void ReplaceKeyword(const char* src, const char* keyword, char* out, size_t outSize);

// vstring版
void ReplaceKeyword(const vstring& src, const vstring& keyword, vstring& out);

関数内で、outのバッファサイズを気にしなくて良くなります。便利!

std::stringの文字列データは、連続したメモリにある事を保証していない。

更に、ヌル終端するとも保証されていません(Effective STL第16項参照)。
つまり以下のコードはダメ。

// 文字列をコピーする
std::string src;
std::string dst;
dst.resize(src.size());
strcpy(&dst.at(0), src.c_str());

代入演算子使えよとかcopy()使えよとか言うツッコミは一旦置いときます。
第2引数に渡しているc_str()は、C形式の文字列を返却するので問題ないですが、
第1引数のatはダメ。


じゃあc_str()をconst_castするのはどうかと言うと、自分は未検証なのでわかりません(;゚∀゚)
でもポリシー的にあまりやりたいと思わないです。


要は、string非constなcharポインタを引数に取る関数とは、相性がよろしく無くて、
そんなのconst付ければいいじゃんって話なんですが、
constを付ける習慣がないC/C++プログラマはかなり多いんじゃないかと思うわけで、
実際今の職場ではかなり多いです。
絶対に変更されない値なんだけども、const付けない。
小規模なら全部書き換えもありえますが、大規模プロジェクトに途中参入だったり
するともうどうしようもないわけでして。


WIN32APIもstringとの相性は微妙と思います。
MultiByteToWideChar関数とかね。


そんな時に重宝するんですvstring。


↑のコードは、vstringでこんな感じに書き換えられます。

// 文字列をコピーする
vstring src;
vstring dst;
dst.resize(src.size()); // srcはヌル終端になっているものとして。
strcpy(&dst[0], &src[0]);

使う時の注意点。

当たり前なんですが終端にヌル文字が要ります

可変長でstringの様に使っていると、忘れがち。

配列が空の場合、&x[0]の返すポインタは未定義の動作を引き起こす。

Effective STL第16項にもある通り、以下の様なコードはダメ。

vstring vstr;  // この時点ではサイズが0!
char* c = &vstr[0];   // これが返すポインタは未定義の動作を引き起こす!