wxStringの概要
wxString overview
Classes: wxString, wxArrayString, wxStringTokenizer
イントロダクションIntroduction
wxStringは任意の長さ(32bitマシン上では通常2147483647であるMAX_INTに制限される)と
任意の文字を含む文字列を表現するクラスである。ASCII NUL文字は許されるが、しかし、それを含む
文字列を他の関数へ渡す際には注意しなければならない。
wxStringはASCII(従来の、7または8bitの文字)でもUnicode(ワイドキャラクタ)でも同様に動作する。
このクラスは、あなたが文字列クラスに期待する全ての標準的操作を持っている:ダイナミック・メモリ・マネージメント(
文字列は新しい文字を収容するために拡張する)、他の文字列からの構築、C文字列と文字、代入演算子、
個々の文字へのアクセス、文字列の連結と比較、サブストリングの抽出、case変換(訳注:大文字、小文字の変換)、
トリミングとパディング(スペースで)、検索と置き換え、そしてCライクな Printf()
とストリームライクな挿入機能、などなど。 - 全ての機能リストに関してはwxString
を参照のこと。
wxString is a class which represents a character string of arbitrary length (limited by
MAX_INT which is usually 2147483647 on 32 bit machines) and containing
arbitrary characters. The ASCII NUL character is allowed, although care should be
taken when passing strings containing it to other functions.
wxString works with both ASCII (traditional, 7 or 8 bit, characters) as well as
Unicode (wide characters) strings.
This class has all the standard operations you can expect to find in a string class:
dynamic memory management (string extends to accommodate new characters),
construction from other strings, C strings and characters, assignment operators,
access to individual characters, string concatenation and comparison, substring
extraction, case conversion, trimming and padding (with spaces), searching and
replacing and both C-like Printf() and stream-like
insertion functions as well as much more - see wxString
for a list of all functions.
wxStringと他の文字列クラスの比較Comparison of wxString to other string classes
C文字列を直接操作する代わりに特別な文字列クラスを使う事の利点は非常に明白なので、このように莫大な数の利用可能なクラスがあるのだ。最も重要な利点は、C文字列はメモリ割り当てと解放を忘れずにする必要があるということだ;固定サイズのバッファの操作は殆ど必然的にバッファオーバーフローを引き起こす。最後に、C++は標準の文字列クラスを持っている。それなのになぜwxStringが必要なのだろう?
The advantages of using a special string class instead of working directly with
C strings are so obvious that there is a huge number of such classes available.
The most important advantage is the need to always
remember to allocate/free memory for C strings; working with fixed size buffers almost
inevitably leads to buffer overflows. At last, C++ has a standard string class
(std::string). So why the need for wxString?
いくつかの利点がある :
- 効率 このクラスは出来る限り効率的に作られた:サイズ(それぞれのwxStringオブジェクトはchar * ポインターとまったく同じスペースをとり、参照のカウントをたれこむ(訳?))と速度の両方において。また、 あなたの特定のアプリケーションのメモリ割り当て方法の調整に使用可能かもしれない、パフォーマンス統計収集コードを提供する - そして利益は大きいかもしれない。
- 互換性 このクラスは、wxWidgets 1.xx wxStringクラスとの最高にちかい互換性、MFC CStringクラスの若干の面影、そしてstd::stringクラスの90%の機能を兼ね備えるよう努める。
- 豊富な関数セット wxStringにある機能のうちのいくつかは非常に有用であるが、ほとんどの他の文字列クラスには存在しない : 例えば、AfterFirst、BeforeLast、<< 演算子、あるいはPrintf。もちろん、全ての標準的文字列操作は同様にサポートされる。
- Unicode wxStringはUnicodeフレンドリーだ : wxStringはどのビルドモードでも(詳しくはUnicode overviewを参照のこと)容易にUnicodeかASCIIの文字列に変換できる.そしてビルドモードに応じてstringかwstringのどちらかに自動的にマップする.
- wxWidgetsによって使用される そして、当然、このクラスはwxWidgets内部の至る所で使用されるので、wxWidgets内部での、他の文字列クラス(std:stringを含む)からwxStringへの変換に起因するパフォーマンス低下がない。
There are several advantages:
- Efficiency This class was made to be as efficient as possible: both
in terms of size (each wxString objects takes exactly the same space as a
char * pointer, sing reference counting) and speed.
It also provides performance statistics gathering code
which may be enabled to fine tune the memory allocation strategy for your
particular application - and the gain might be quite big.
- Compatibility This class tries to combine almost full compatibility
with the old wxWidgets 1.xx wxString class, some reminiscence to MFC CString
class and 90% of the functionality of std::string class.
- Rich set of functions Some of the functions present in wxString are
very useful but don't exist in most of other string classes: for example,
AfterFirst,
BeforeLast, operator<<
or Printf. Of course, all the standard string
operations are supported as well.
- Unicode wxString is Unicode friendly: it allows to easily convert
to and from ANSI and Unicode strings in any build mode (see the
Unicode overview for more details) and maps to either
string or wstring transparently depending on the current mode.
- Used by wxWidgets And, of course, this class is used everywhere
inside wxWidgets so there is no performance loss which would result from
conversions of objects of any other string class (including std::string) to
wxString internally by wxWidgets.
しかしながら、同様にいくつかの問題もある。最も重要な問題の一つは恐らく、全く同じことをする関数が複数存在する事だ : 例えば、文字列の長さを得るためにlength()、Len()、Length()の何れが使われてもよい。最初の関数は、他のほとんど全ての小文字の関数と同様に、std::string互換である。二番目の関数は、wxStringネイティブであり、最後のものはwxWidgets 1.xx の方法である。そして問題は : どれを使うのがベターか? そして答えは :
std:string互換関数の利用が強く推奨される! それは、あなたのコードを他のC++プログラマ(std::stringについての知識はあるが、wxStringの知識はないと想定される)にとってより見慣れたものにするだろうし、
あなたがwxWidgetsと他のプログラムの両方の中で同じコードを共有できるようにする(wxWidgets以外のプログラムでは、
単にwxStringをstd::stringとtypedefすればよい)、そして遅かれ早かれstd::stringを使い始めるであろうwxWidgetsの将来の
バージョンとの互換性を保つ.
対応するstd::stringの関数がない場合、どうか、軽視され、そして将来のバージョンで姿を消すかもしれない、古いwxWidgets 1.xx バージョンではなく、新しいwxStringのメソッドを使うようにして下さい。
However, there are several problems as well. The most important one is probably
that there are often several functions to do exactly the same thing: for
example, to get the length of the string either one of
length(), Len() or
Length() may be used. The first function, as almost
all the other functions in lowercase, is std::string compatible. The second one
is "native" wxString version and the last one is wxWidgets 1.xx way. So the
question is: which one is better to use? And the answer is that:
The usage of std::string compatible functions is strongly advised! It will
both make your code more familiar to other C++ programmers (who are supposed to
have knowledge of std::string but not of wxString), let you reuse the same code
in both wxWidgets and other programs (by just typedefing wxString as std::string
when used outside wxWidgets) and by staying compatible with future versions of
wxWidgets which will probably start using std::string sooner or later too.
In the situations where there is no corresponding std::string function, please
try to use the new wxString methods and not the old wxWidgets 1.xx variants
which are deprecated and may disappear in future versions.
wxStringを使う上でのアドバイス
Some advice about using wxString
多分,このクラスを使う時の主な問題は
const char *への暗黙型変換であろう.
変換が行われている事を明確にするため,
c_str()を用いることを推奨する.
暗黙型変換の危険性はこのコードに明確に見られる.
Probably the main trap with using this class is the implicit conversion operator to
const char *. It is advised that you use
c_str()
instead to clearly indicate when the conversion is done. Specifically, the
danger of this implicit conversion may be seen in the following code fragment:
// この関数はinput文字列を大文字に変換したoutput文字列を作成し,それを画面に出力してから返す.
// this function converts the input string to uppercase, output it to the screen
// and returns the result
const char *SayHELLO(const wxString& input)
{
wxString output = input.Upper();
printf("Hello, %s!\n", output);
return output;
}
この3行に2つのいやらしいバグが存在する.
1つ目はprintf()関数の呼び出しの中にある.
C言語タイプ文字列への暗黙型変換は↓ケースでは自動的に行われる.
There are two nasty bugs in these three lines. First of them is in the call to the
printf() function. Although the implicit conversion to C strings is applied
automatically by the compiler in the case of
puts(output);
なぜなら
puts()の引数の型は
const char *だと判っているからだ.
printf()は複数・多種類の引数を受け取るので,
この暗黙型変換は行われない.
よってこの実行結果は不定であり,正しく画面に出力するかもしれないし,クラッシュするかもしれない.
解決法は,単にこのように
c_str()に置き換える事だ.
because the argument of
puts() is known to be of the type
const char *,
this is
not done for
printf() which is a function with variable
number of arguments (and whose arguments are of unknown types). So this call may
do anything at all (including displaying the correct string on screen), although
the most likely result is a program crash. The solution is to use
c_str(): just replace this line with
printf("Hello, %s!\n", output.c_str());
2つ目のバグはoutputのreturnが働かない事だ.
暗黙型変換が行われるようにコンパイルされるが,関数が終了すると同時に破棄される変数に属する
バッファへのポインタが返されるため,実行結果は不定である.
この解決法も簡単である.関数がC言語タイプ文字列の代わりにwxStringを返すようにすれば良い.
The second bug is that returning output doesn't work. The implicit cast is
used again, so the code compiles, but as it returns a pointer to a buffer
belonging to a local variable which is deleted as soon as the function exits,
its contents is totally arbitrary. The solution to this problem is also easy:
just make the function return wxString instead of a C string.
このことは次の一般的な助言を導く:全ての文字列を引数に取る関数は,
const wxString&を
取る(これは関数内への文字列の割り当てを高速にする.
reference countingを参照)
べきであり,全ての文字列を返す関数は
wxStringを返す(これはローカル変数を
安全に返す)べきである.
This leads us to the following general advice: all functions taking string
arguments should take
const wxString& (this makes assignment to the
strings inside the function faster because of
reference counting) and all functions returning
strings should return
wxString - this makes it safe to return local
variables.
その他の文字列に関した関数とクラス
Other string related functions and classes
多くのプログラムは文字列を使用し,標準Cライブラリはかなりの数の文字列に関する関数を提供する.
不幸な事に,それらの関数のいくつかは直感できでない動作をする.(例えば,strncpy()がコピーした
文字列がNULL文字で終わるとは限らない)そして大概,あまり安全ではない.(それらの関数にNULLを渡したら,
プログラムがクラッシュするかもしれない)
それに加えて,幾つかのとても便利な関数は標準でない事もある.
これが,wxString関数に加えて,幾つかのグローバル関数が以下の問題を解決するために用意された理由である:
wxIsEmpty()は文字列が空かどうかを判定する(
NULLポインタを
渡されたら
TRUEを返す).
wxStrlen()もNULLが渡されたら0を返す.
wxStricmp()は単にプラットフォームから独立した大文字/小文字を区別しない
文字列比較であり,プラットフォーム依存のstricmp(),strcasecmp()として知られている関数と同じである.
As most programs use character strings, the standard C library provides quite
a few functions to work with them. Unfortunately, some of them have rather
counter-intuitive behaviour (like strncpy() which doesn't always terminate the
resulting string with a NULL) and are in general not very safe (passing NULL
to them will probably lead to program crash). Moreover, some very useful
functions are not standard at all. This is why in addition to all wxString
functions, there are also a few global string functions which try to correct
these problems:
wxIsEmpty() verifies whether the string
is empty (returning
TRUE for
NULL pointers),
wxStrlen() also handles NULLs correctly and returns 0 for
them and
wxStricmp() is just a platform-independent
version of case-insensitive string comparison function known either as
stricmp() or strcasecmp() on different platforms.
The
<wx/string.h> header also defines
wxSnprintf
and
wxVsnprintf functions which should be used instead
of the inherently dangerous standard
sprintf() and which use
snprintf() instead which does buffer size checks whenever possible. Of
course, you may also use
wxString::Printf which is
also safe.
他にも,wxStringと共に用いる便利なクラス
wxStringTokenizerがある.
これは文字列をトークンに分解する時に役立ち,標準Cライブラリの
strtok()関数を置き換える.
There is another class which might be useful when working with wxString:
wxStringTokenizer. It is helpful when a string must
be broken into tokens and replaces the standard C library
strtok() function.
最後の文字列に関するクラスは,
wxArrayStringである.
これは文字列専用バージョンの動的配列である.
このクラスは(格納しているのがwxStringであるという前提を用いて)特別に最適化されていて,ただの
wxStringのwxObjectArrayよりも断然パフォーマンス面で優れいていることに注意して欲しい.
And the very last string-related class is
wxArrayString: it
is just a version of the "template" dynamic array class which is specialized to work
with strings. Please note that this class is specially optimized (using its
knowledge of the internal structure of wxString) for storing strings and so it is
vastly better from a performance point of view than a wxObjectArray of wxStrings.
参照カウントと,それを開発者が気にしないで良い理由
Reference counting and why you shouldn't care about it
wxStringクラスはcopy on write (COW)として知られているテクニックを用いている.
これはある文字列が別のオブジェクトに割り当てられた時,実際のコピーは行われず,リファレンス
カウントがインクリメントされ,2つのオブジェクトは同じ文字列データを共有するだけである
事を意味する.
wxString objects use a technique known as copy on write (COW). This means
that when a string is assigned to another, no copying really takes place: only
the reference count on the shared string data is incremented and both strings
share the same data.
しかし同じ文字列を共用している複数のオブジェクトのうち一つが変更されるとき,文字列は
コピーされ他のオブジェクトには影響しない.
データのコピーは文字列が書き込まれる時にしか行われない,これがCOWとして知られているものである.
But as soon as one of the two (or more) strings is modified, the data has to be
copied because the changes to one of the strings shouldn't be seen in the
others. As data copying only happens when the string is written to, this is
known as COW.
理解しておかないといけない重要な事は,これらの全ての事はクラスのユーザーに対して
完全に透過的(ユーザーに意識されず)に行われる事と,文字列が共有されているかいないかは
クラスの外からは関係なく,全ての処理の結果がどんな場合も同じになることだ.
What is important to understand is that all this happens absolutely
transparently to the class users and that whether a string is shared or not is
not seen from the outside of the class - in any case, the result of any
operation on it is the same.
多分,開発者が参照カウントについて考えたくなる唯一のケースは,非const(もしくはconst参照)の
文字列から文字を取り出すときであろう.
このケースでは,C++のルールにより,読み込み専用の
operator[]
(
GetChar()と同じ)
は選ばれず,読み書き可能な
operator[]
(
GetWritableChar())と同じ)
が代わりに用いられる.
この演算子は文字列を変更できるので,コピーが行われる.そしてそれが共有されていた文字列なら,
パフォーマンス(時間とメモリ使用量の両方で)のロスが生じる.
このまれなケースでは,
GetChar()を前述の理由で用いる
方が良い.
at()関数も同じ問題を抱えているので,この関数を
使うのはあまり良くないということに注意して欲しい.
また,全ての文字列引数を
const wxString&(
Some advice
を参照)としてとる関数では,このような状況は殆ど全く生じない(const参照からはconst演算子が自動的に
呼ばれるから)ことも覚えておくと良い.
Probably the unique case when you might want to think about reference
counting is when a string character is taken from a string which is not a
constant (or a constant reference). In this case, due to C++ rules, the
"read-only"
operator[] (which is the same as
GetChar()) cannot be chosen and the "read/write"
operator[] (the same as
GetWritableChar()) is used instead. As the
call to this operator may modify the string, its data is unshared (COW is done)
and so if the string was really shared there is some performance loss (both in
terms of speed and memory consumption). In the rare cases when this may be
important, you might prefer using
GetChar() instead
of the array subscript operator for this reasons. Please note that
at() method has the same problem as the subscript operator in
this situation and so using it is not really better. Also note that if all
string arguments to your functions are passed as
const wxString& (see the
section
Some advice) this situation will almost
never arise because for constant references the correct operator is called automatically.
あなたのアプリケーションのためのwxStringのチューニング
Tuning wxString for your application
注意:このセクションは性能に関することだけを扱い,wxStringクラスを利用するために
読む必用は無い.
プロファイラや関連したツールに慣れ親しんだ人以外は読み飛ばしてください.
もしこのセクションを読むのなら,先に書いた
参照カウント
についてのセクションも読んでください.
Note: this section is strictly about performance issues and is
absolutely not necessary to read for using wxString class. Please skip it unless
you feel familiar with profilers and relative tools. If you do read it, please
also read the preceding section about
reference counting.
性能のために,wxStringは各々の文字列に,必用な量と同じ量のメモリを確保しません.
そうではなく,必要とされるより少し多くのメモリを確保し,頻繁に再確保が行われないようにします.
例えば,下の例で示されるように,構築された文字列にあとから文字が追加されたるような時:
For the performance reasons wxString doesn't allocate exactly the amount of
memory needed for each string. Instead, it adds a small amount of space to each
allocated block which allows it to not reallocate memory (a relatively
expensive operation) too often as when, for example, a string is constructed by
subsequently adding one character at a time to it, as for example in:
// 全ての母音を文字列から削除する
// delete all vowels from the string
wxString DeleteAllVowels(const wxString& original)
{
wxString result;
size_t len = original.length();
for ( size_t n = 0; n < len; n++ )
{
if ( strchr("aeuio", tolower(original[n])) == NULL )
result += original[n];
}
return result;
}
このような状況はとてもよく起こり,余分なメモリを確保していなかったらとても性能が低下する.
なぜなら元の文字列の中の子音の数と同じだけのメモリの再確保が起こるからだ.
必要以上なメモリの確保は,この状況では速度の向上に役立つ.
しかし,大量のwxStringが使われるアプリケーションでは,メモリを大量に消費する事になってしまう.
This is quite a common situation and not allocating extra memory at all would
lead to very bad performance in this case because there would be as many memory
(re)allocations as there are consonants in the original string. Allocating too
much extra memory would help to improve the speed in this situation, but due to
a great number of wxString objects typically used in a program would also
increase the memory consumption too much.
この(上のサンプル関数の)場合確実に最も良い方法は,Alloc()関数を
用いてメモリをpreallocateすることだ.
例えば,lenバイトのメモリをpreallocateすれば,メモリ確保は一回のみで済む.
(最大でも元の文字列と同じ大きさにしかならないから)
The very best solution in precisely this case would be to use
Alloc() function to preallocate, for example, len bytes
from the beginning - this will lead to exactly one memory allocation being
performed (because the result is at most as long as the original string).
しかしながら,Alloc()を使うのはめんどくさいし,wxStringは(Alloc()を使わなくても)ベストを尽くす.
デフォルトのアルゴリズムでは,最低16バイトの粒度のメモリが確保される(広く使われている
殆どのプラットフォームではそうなっている)と仮定する.だから16の倍数に繰り上げたメモリを確保しても
全く無駄が生じない.
このように,全く無駄にメモリを消費する事が無く,上の例では16文字毎に15回はメモリの割り当てが行われ
ずに,使っていないメモリを用いる.
However, using Alloc() is tedious and so wxString tries to do its best. The
default algorithm assumes that memory allocation is done in granularity of at
least 16 bytes (which is the case on almost all of wide-spread platforms) and so
nothing is lost if the amount of memory to allocate is rounded up to the next
multiple of 16. Like this, no memory is lost and 15 iterations from 16 in the
example above won't allocate memory but use the already allocated pool.
デフォルトの方法は全く保守的である.
メモリの余分な確保は,(比較的に)とても長い幾つかの文字列を使うプログラムに大きなパフォーマンスの向上をもたらす.
確保するメモリの量は,string.cppファイルの中のEXTRA_ALLOCによって,コンパイル時に決まる.
(この値を変えるときは,デフォルト値が何故使われいてるのかを確実に理解する事)
開発者はこの値をより大きい値(例えばnLenの倍)か0(それによる速度低下を知るため)に設定して,
自分のプログラムに与える影響を調査するかもしれない.
もしそうするなら,wxStringクラスにパフォーマンスの統計を集めさせ,それをプログラム
終了時にstderrに出力するように支持するWXSTRING_STATISTICSを宣言すると役に立つだろう.
これはプログラムが扱う文字列の平均長,初期の長さ,文字列の連結が行われた時にメモリの再確保が
行われずにすんだ割合(この値はデフォルトのポリシーでは約98%であるべきである.もしこれが90%未満
なら,開発者はそのアプリケーションの為にwxStringのチューニングを考えるべきである)を表示する.
The default approach is quite conservative. Allocating more memory may bring
important performance benefits for programs using (relatively) few very long
strings. The amount of memory allocated is configured by the setting of
EXTRA_ALLOC in the file string.cpp during compilation (be sure to understand
why its default value is what it is before modifying it!). You may try setting
it to greater amount (say twice nLen) or to 0 (to see performance degradation
which will follow) and analyse the impact of it on your program. If you do it,
you will probably find it helpful to also define WXSTRING_STATISTICS symbol
which tells the wxString class to collect performance statistics and to show
them on stderr on program termination. This will show you the average length of
strings your program manipulates, their average initial length and also the
percent of times when memory wasn't reallocated when string concatenation was
done but the already preallocated memory was used (this value should be about
98% for the default allocation policy, if it is less than 90% you should
really consider fine tuning wxString for your application).
言うまでもなく,EXTRA_ALLOCの値の変更がプログラムに与える影響を
正確に測るためにプロファイラを用いるべきである.
It goes without saying that a profiler should be used to measure the precise
difference the change to EXTRA_ALLOC makes to your program.