C ++でsの配列を管理するために、いつ使用するstd::string
必要があり、いつ使用する必要がありますか?char*
char
char*
パフォーマンス(速度)が重要であり、メモリ管理のためにリスクの高いビジネスの一部を受け入れる意思がある場合は、使用する必要があるようです。
考慮すべき他のシナリオはありますか?
私の見解は次のとおりです。
コピーを避けるためにsが大きい場合は参照によって、またはインスタンスへのポインターを渡すことができるstd::string
ため、ポインターを使用した実際の利点はわかりませんchar
。
私はstd::string
/wstring
を多かれ少なかれ実際のテキストであるすべてに使用します。char *
ただし、他のタイプのデータには便利であり、本来のように割り当てが解除されることを確認できます。そうstd::vector<char>
でなければ行く方法です。
これらすべてにはおそらく例外があります。
はい、時々あなたは本当にこれを行うことができます。const char *、スタックに割り当てられたchar配列、および文字列リテラルを使用する場合、メモリ割り当てがまったくないような方法でそれを行うことができます。
このようなコードを書くには、文字列やベクトルを使用するよりも多くの場合、より多くの思考と注意が必要ですが、適切な手法を使用すれば実行できます。適切な手法を使用すれば、コードは安全ですが、char []にコピーするときは、コピーする文字列の長さを保証するか、特大の文字列を適切にチェックして処理する必要があります。そうしないことが、strcpyファミリーの関数に安全ではないという評判を与えた理由です。
char []バッファの安全性については、バッファサイズを処理するためのカプセル化を作成できるため、テンプレートが役立ちます。このようなテンプレートは、strcpyの安全な代替品を提供するために、たとえばMicrosoftによって実装されています。ここでの例は私自身のコードから抽出されたものであり、実際のコードにはさらに多くのメソッドがありますが、これは基本的な考え方を伝えるのに十分なはずです。
template <int Size>
class BString
{
char _data[Size];
public:
BString()
{
_data[0]=0;
// note: last character will always stay zero
// if not, overflow occurred
// all constructors should contain last element initialization
// so that it can be verified during destruction
_data[Size-1]=0;
}
const BString &operator = (const char *src)
{
strncpy(_data,src,Size-1);
return *this;
}
operator const char *() const {return _data;}
};
//! overloads that make conversion of C code easier
template <int Size>
inline const BString<Size> & strcpy(BString<Size> &dst, const char *src)
{
return dst = src;
}
使用しなければならない場合とそうでない場合の1つchar*
はstd::string
、静的文字列定数が必要な場合です。その理由は、モジュールが静的変数を初期化する順序を制御できず、別のモジュールの別のグローバルオブジェクトが、初期化される前に文字列を参照する可能性があるためです。http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variables
std::string
長所:
std::string
短所:-2つの異なるSTL文字列インスタンスは、同じ基になるバッファを共有できません。したがって、値を渡すと、常に新しいコピーが取得されます。-パフォーマンスの低下はありますが、特別な要件がない限り、無視できると思います。
char*
次の場合に使用することを検討する必要があります。
実際、C ++では、char*
オプション、ファイル名などとして、固定された小さな単語によく使用されます...
c ++ std :: stringを使用する場合:
string
s全体として、より安全ですchar*
。通常、あなたが何かをしているときは、char*
物事が正しいことを確認するために物事をチェックする必要がありstring
ます。クラスでは、これはすべてあなたのために行われます。char*
を行う必要はありません。string
string
■C++でうまく機能しstringstream
、フォーマットされたIOは非常に簡単です。charを使用する場合*
char*
すると、舞台裏で何が起こっているかをより細かく制御できます。つまり、必要に応じてパフォーマンスを調整できます。ライブラリを作成する場合は、パラメータとして(const)char*を使用します。std :: stringの実装は、コンパイラによって異なります。
Cライブラリを使用する場合は、C文字列を処理する必要があります。APIをCに公開する場合も同様です。
std :: string(egなどfind
)に対するほとんどの操作は可能な限り最適化されることが期待できるため、少なくとも純粋なCの対応物と同様に実行される可能性があります。
std :: stringイテレータは、基になるchar配列へのポインタにマップされることがよくあることにも注意してください。したがって、イテレータの上で考案するアルゴリズムは、パフォーマンスの点でchar*の上にある同じアルゴリズムと本質的に同じです。
注意すべき点は次のとおりです。たとえば、operator[]
ほとんどのSTL実装は境界チェックを実行しないため、これを基になる文字配列に対する同じ操作に変換する必要があります。AFAIK STLPortはオプションで境界チェックを実行できます。その時点で、この演算子は少し遅くなります。
では、std :: stringを使用すると何が得られますか?手動のメモリ管理から解放されます。アレイのサイズ変更が簡単になり、通常、メモリの解放について考える必要が少なくなります。
文字列のサイズを変更するときにパフォーマンスが心配reserve
な場合は、便利な関数があります。
テキストなどで文字の配列を使用している場合は、std::stringをより柔軟で使いやすく使用してください。データストレージのような他の目的で使用する場合はどうなりますか?配列を使用する(ベクトルを優先する)
パフォーマンスが重要な場合でも、より適切に使用vector<char>
できます。事前にメモリを割り当てることができ(reserve()メソッド)、メモリリークを回避するのに役立ちます。vector :: operator []を使用するとオーバーヘッドが発生しますが、いつでもバッファのアドレスを抽出して、char*の場合とまったく同じようにインデックスを付けることができます。
AFAIKは、内部的にほとんどのstd :: stringにコピーオンライトを実装し、文字列が参照によって渡されない場合でも、オーバーヘッドを回避するためにカウントされたセマンティクスを参照します。