C ++でsの配列を管理するためstd::string
に、いつ使用する必要があり、いつ使用する必要がありますか?char*
char
char*
パフォーマンス(速度)が重要であり、メモリ管理のためにリスクの高いビジネスの一部を受け入れても構わないと思っている場合は、使用する必要があるようです。
考慮すべき他のシナリオはありますか?
回答:
std :: stringが大きい場合は、コピーを避けるために参照によって渡すか、インスタンスへのポインターを渡すことができるため、charポインターを使用しても実際の利点はわかりません。
私は実際のテキストである多かれ少なかれすべてにstd :: string / wstringを使用します。char *
ただし、他のタイプのデータには便利であり、必要に応じて割り当てが解除されることを確認できます。それ以外の場合は、std :: vectorが最適です。
これらすべてにはおそらく例外があります。
char *
はほとんどオーバーヘッドがありません。正確にどのようなオーバーヘッドstd::string
があるのかはわかりませんが、実装に依存する可能性があります。オーバーヘッドが裸のcharポインターのオーバーヘッドよりもはるかに大きくなることはほとんど期待できません。私は規格のコピーを所有していないので、規格によって行われた保証について詳しく説明することはできません。パフォーマンスの違いは、実行する操作によって異なる可能性があります。std::string::size
文字データの横にサイズを格納できるため、よりも高速になりstrlen
ます。
append(const string&)
、バイナリセーフ操作のみを使用するように注意する必要があります。append(const char*, size_t)
operator+=()
はい、時々あなたは本当にこれを行うことができます。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;
}
char*
文字列は常にスタック上にあるとは限りません。char *str = (char*)malloc(1024); str[1024] = 0;
使用char*
しなければならない場合と使用しない場合の1つstd::string
は、静的文字列定数が必要な場合です。その理由は、モジュールが静的変数を初期化する順序を制御できず、別のモジュールの別のグローバルオブジェクトが、初期化される前に文字列を参照する可能性があるためです。http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variables
std::string
長所:
std::string
短所:-2つの異なるSTL文字列インスタンスが同じ基になるバッファを共有することはできません。したがって、値を渡すと、常に新しいコピーが取得されます。-パフォーマンスの低下はありますが、要件が特別でない限り、無視できると思います。
c ++ std :: stringを使用する場合:
char *を使用する場合
ライブラリーを作成する場合は、パラメーターとして(const)char *を使用してください。std :: stringの実装は、コンパイラによって異なります。
std :: string(egなどfind
)に対するほとんどの操作は可能な限り最適化されることが期待できるため、少なくとも純粋なCの対応物と同様に実行される可能性があります。
std :: stringイテレータは、基になるchar配列へのポインタにマップされることがよくあることにも注意してください。したがって、イテレータの上で考案したアルゴリズムは、パフォーマンスの点でchar *の上にある同じアルゴリズムと本質的に同じです。
注意すべき点は次のとおりです。たとえば、operator[]
ほとんどのSTL実装は境界チェックを実行しないため、これを基になる文字配列に対する同じ操作に変換する必要があります。AFAIK STLPortはオプションで境界チェックを実行できます。その時点で、この演算子は少し遅くなります。
では、std :: stringを使用すると何が得られますか?手動のメモリ管理から解放されます。アレイのサイズ変更が簡単になり、通常、メモリの解放について考える必要が少なくなります。
文字列のサイズを変更するときにパフォーマンスが心配reserve
な場合は、便利な関数があります。
パフォーマンスが重要な場合でも、より適切に使用vector<char>
できます。事前にメモリを割り当てることができ(reserve()メソッド)、メモリリークを回避するのに役立ちます。vector :: operator []を使用するとオーバーヘッドが発生しますが、いつでもバッファのアドレスを抽出して、char *の場合とまったく同じようにインデックスを付けることができます。