char * vs c ++のstd :: string [終了]
質問
C ++でstd::string
の配列を管理するために、いつchar*
を使用し、char
を使用すべきですか?
パフォーマンス(速度)が重要であり、メモリ管理のためにリスクのあるビジネスを受け入れたい場合は、<=>を使用する必要があるようです。
考慮すべき他のシナリオはありますか?
解決
std :: stringsがコピーを避けるために大きい場合は参照によって、またはインスタンスへのポインターを渡すことができます。したがって、charポインターを使用することの本当の利点はありません。
実際のテキストであるすべてのものに多かれ少なかれstd :: string / wstringを使用します。 char *
は他のタイプのデータにも役立ちますが、必要なように割り当て解除されることを確認できます。それ以外の場合は、std :: vectorを使用します。
おそらくこれらすべてには例外があります。
他のヒント
私の視点:
- <!> quot; C <!> quot;を呼び出さない場合は、char *を使用しないでください。コード。
- 常にstd :: stringを使用する:より簡単で、より使いやすく、最適化され、標準であり、バグの発生を防ぎ、チェックされ、動作することが証明されています。
生の文字列の使用
はい、時々あなたは本当にこれを行うことができます。 const char *、スタックに割り当てられたchar配列、および文字列リテラルを使用する場合、メモリ割り当てがまったくないような方法で実行できます。
このようなコードを書くには、多くの場合、文字列やベクトルを使用するよりも多くの思考と注意が必要ですが、適切なテクニックを使用してそれを行うことができます。適切な手法を使用するとコードは安全になりますが、char []にコピーするときは、コピーする文字列の長さを保証するか、サイズの大きい文字列を適切にチェックして処理する必要があります。そうしないと、strcpyファミリーの関数に安全でないという評判が与えられます。
テンプレートが安全な文字バッファーの作成に役立つ方法
char []バッファーの安全性に関しては、バッファーサイズを処理するためのカプセル化を作成できるため、テンプレートが役立ちます。このようなテンプレートは実装されていますMicrosoftがstrcpyの安全な代替品を提供します。ここの例は自分のコードから抽出されたもので、実際のコードにはもっと多くのメソッドがありますが、これは基本的な考え方を伝えるのに十分なはずです:
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*
ではなくstd::string
を使用する必要があります。その理由は、静的な変数を初期化する注文モジュールを制御できないため、別のモジュールの別のグローバルオブジェクトが初期化される前に文字列を参照する可能性があるためです。 http://google-styleguide.googlecode.com/svn/trunk/ cppguide.xml#Static_and_Global_Variables
<=>長所:
- メモリを管理します(文字列が大きくなる可能性があり、実装により大きなバッファが割り当てられます)
- 高レベルのプログラミングインターフェイス、他のインターフェイスとうまく機能 STLの。
<=>短所: -2つの別個のSTL文字列インスタンスは、同じ基礎バッファを共有できません。したがって、値で渡すと、常に新しいコピーが取得されます。 -パフォーマンスにはいくらかのペナルティがありますが、要件が特別でない限り無視できると思います。
次の場合にはchar*
の使用を検討する必要があります。
- この配列はパラメーターで渡されます。
- 事前に配列の最大サイズを知っています(知っているか、課す)。
- この配列では変換を行いません。
実際には、C ++では、<=>はオプション、ファイル名など、固定された小さな単語によく使用されます...
C ++ std :: string:を使用する場合
- 文字列は全体的にchar *よりも安全です。通常、char *を使用して作業を行う場合は、文字列クラスですべてを実行して、正しいことを確認する必要があります。
- 通常、char *を使用する場合は、割り当てたメモリを解放する必要があります。破壊されると内部バッファが解放されるため、stringを使用する必要はありません。
- 文字列はc ++ stringstreamでうまく機能し、フォーマットされたIOは非常に簡単です。
char *を使用する場合
- char *を使用すると、<!> quot; behind <!> quot;必要に応じてパフォーマンスを調整できることを意味します。
ライブラリを作成する場合は、(const)char *をパラメーターとして使用します。 std :: stringの実装は、コンパイラごとに異なります。
Cライブラリを使用する場合は、C文字列を処理する必要があります。 APIをCに公開する場合も同様です。
std :: stringのほとんどの操作(たとえば、find
など)は可能な限り最適化されることが期待できるため、少なくとも純粋なCの同等物と同様に実行される可能性があります。
また、std :: stringイテレータは、基本となるchar配列へのポインターにマップされることが多いことに注意してください。したがって、イテレータの上で考案したアルゴリズムは、パフォーマンスの点でchar *の上で同じアルゴリズムと本質的に同一です。
注意すべき点は、たとえばoperator[]
-ほとんどのSTL実装は境界チェックを実行しないため、これを基礎となる文字配列での同じ操作に変換する必要があります。 AFAIK STLPortは、オプションで境界チェックを実行できます。この時点で、この演算子は少し遅くなります。
では、std :: stringを使用すると何が得られますか?手動のメモリ管理から解放されます。配列のサイズ変更が簡単になり、一般的にメモリの解放について考える必要が少なくなります。
文字列のサイズを変更する際のパフォーマンスが心配な場合は、便利なreserve
関数があります。
文字などの文字の配列を使用している場合は、std :: stringをより柔軟で使いやすいものに使用します。データストレージのような他の用途に使用する場合は?配列を使用(ベクトルを優先)
パフォーマンスが重要な場合でも、vector<char>
を使用することをお勧めします-事前にメモリを割り当てることができ(reserve()メソッド)、メモリリークを回避できます。 vector :: operator []を使用するとオーバーヘッドが発生しますが、いつでもバッファーのアドレスを抽出し、char *であるかのようにインデックスを作成できます。
内部では、ほとんどのstd :: stringは、文字列が参照渡しされない場合でも、オーバーヘッドを回避するために書き込み時のコピー、参照カウントセマンティクスを実装します。