web-dev-qa-db-ja.com

C ++でのchar *とstd :: string

いつstd::stringを使用し、char*を使用してcharsの配列をC++で管理する必要がありますか?

パフォーマンス(速度)が重要であり、メモリ管理のためにリスクのあるビジネスを受け入れたい場合は、char*を使用する必要があります。

考慮すべき他のシナリオはありますか?

78
anon

コピーを避けるために大きい場合はstd :: stringsを参照で渡すことができます。または、インスタンスへのポインターなので、charポインターを使用しても実際には利点がありません。

私は、実際のテキストである多かれ少なかれすべてにstd :: string/wstringを使用します。 char *は、他のタイプのデータにも役立ちますが、確実に解放されるはずです。それ以外の場合は、std :: vectorを使用します。

おそらくこれには例外があります。

55
Skurmedel

私の視点は次のとおりです。

  • 「C」コードを呼び出さない場合は、char *を使用しないでください。
  • 常にstd :: stringを使用してください:より簡単で、より使いやすく、最適化され、標準であり、バグの発生を防ぎ、チェックされ、動作することが証明されています。
54
Gal Goldman

生の文字列の使用

はい、時々あなたは本当にこれを行うことができます。 const char *、スタックに割り当てられたchar配列、および文字列リテラルを使用する場合、メモリ割り当てがまったくないような方法で実行できます。

そのようなコードを書くには、多くの場合、文字列やベクトルを使用するよりも多くの思考と注意が必要ですが、適切なテクニックを使用してそれを行うことができます。適切な手法を使用するとコードは安全になりますが、char []にコピーするときは、コピーする文字列の長さをある程度保証するか、サイズの大きい文字列を適切にチェックして処理する必要があります。そうしないことは、strcpyファミリーの関数に安全でないという評判を与えたものです。

テンプレートが安全な文字バッファーの作成にどのように役立つか

Char []バッファーの安全性に関しては、テンプレートが役立つ場合があります。これは、バッファーサイズを処理するためのカプセル化を作成できるためです。このようなテンプレートは実装されています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;
}
13
Suma

char*ではなくstd::stringを使用する必要がある場合の1つは、静的な文字列定数が必要な場合です。その理由は、静的変数を初期化する順序モジュールを制御できないため、別のモジュールの別のグローバルオブジェクトが初期化される前に文字列を参照する可能性があるためです。 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variables

std::string長所:

  • メモリを管理します(文字列は大きくなる可能性があり、実装はより大きなバッファを割り当てます)
  • 高レベルのプログラミングインターフェイスは、STLの残りの部分とうまく機能します。

std::string短所:-2つの異なるSTL文字列インスタンスは、同じ基礎となるバッファーを共有できません。したがって、値で渡すと、常に新しいコピーが取得されます。 -パフォーマンスには多少のペナルティがありますが、要件が特別でない限り無視できると思います。

9
thesamet

次の場合には、char*の使用を検討する必要があります。

  • この配列はパラメーターで渡されます。
  • 配列の最大サイズを事前に知っています(それを知っているOR強制する)。
  • この配列では変換を行いません。

実際、C++では、char*は多くの場合、オプション、ファイル名など、固定された小さなWordに使用されます。

8
Jérôme

C++ std :: string:を使用する場合

  • 文字列は全体的に、char *よりも安全です。通常、char *を使用して作業を行う場合は、文字列クラスですべてを実行して、正しいことを確認する必要があります。
  • 通常、char *を使用する場合、割り当てたメモリを解放する必要があります。文字列を使用する必要はありません。破壊されると内部バッファが解放されるためです。
  • 文字列はc ++ stringstreamでうまく機能し、IOは非常に簡単です。

char *を使用する場合

  • Char *を使用すると、シーンの「背後」で発生していることをより詳細に制御できます。つまり、必要に応じてパフォーマンスを調整できます。
5
user88637

ライブラリを作成する場合は、(const)char *をパラメーターとして使用します。 std :: stringの実装は、コンパイラによって異なります。

3

Cライブラリを使用する場合は、C文字列を処理する必要があります。 APIをCに公開する場合も同様です。

2
n0rd

Std :: stringのほとんどの操作(たとえばfindなど)は可能な限り最適化されることが期待できるため、少なくとも純粋なCの同等物と同様に実行される可能性があります。

また、std :: string反復子は、基になるchar配列へのポインターにマップされることが非常に多いことに注意してください。したがって、イテレータの上で考案したアルゴリズムは、パフォーマンスの点でchar *の上で同じアルゴリズムと本質的に同一です。

気をつけるべきことは、例えばoperator[]-ほとんどのSTL実装は境界チェックを実行せず、これを基礎となる文字配列の同じ操作に変換する必要があります。 AFAIK STLPortはオプションで境界チェックを実行できます。この時点で、この演算子は少し遅くなります。

では、std :: stringを使用すると何が得られますか?手動のメモリ管理から解放されます。配列のサイズ変更が容易になり、一般にメモリの解放について考える必要が少なくなります。

文字列のサイズを変更するときのパフォーマンスが心配な場合は、便利なreserve関数があります。

2
unwesen

テキストなどの文字の配列を使用している場合は、std :: stringを使用して、より柔軟で使いやすくします。データストレージのような他の用途に使用する場合は?配列を使用(ベクトルを優先)

1
RvdK

パフォーマンスが重要な場合でも、vector<char>-事前にメモリ割り当てを許可し(reserve()メソッド)、メモリリークを回避するのに役立ちます。 vector :: operator []を使用するとオーバーヘッドが発生しますが、常にバッファーのアドレスを抽出し、char *の場合とまったく同じようにインデックスを付けることができます。

1
sharptooth