いつstd::string
を使用し、char*
を使用してchar
sの配列をC++で管理する必要がありますか?
パフォーマンス(速度)が重要であり、メモリ管理のためにリスクのあるビジネスを受け入れたい場合は、char*
を使用する必要があります。
考慮すべき他のシナリオはありますか?
コピーを避けるために大きい場合はstd :: stringsを参照で渡すことができます。または、インスタンスへのポインターなので、charポインターを使用しても実際には利点がありません。
私は、実際のテキストである多かれ少なかれすべてにstd :: string/wstringを使用します。 char *
は、他のタイプのデータにも役立ちますが、確実に解放されるはずです。それ以外の場合は、std :: vectorを使用します。
おそらくこれには例外があります。
私の視点は次のとおりです。
はい、時々あなたは本当にこれを行うことができます。 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;
}
char*
ではなくstd::string
を使用する必要がある場合の1つは、静的な文字列定数が必要な場合です。その理由は、静的変数を初期化する順序モジュールを制御できないため、別のモジュールの別のグローバルオブジェクトが初期化される前に文字列を参照する可能性があるためです。 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variables
std::string
長所:
std::string
短所:-2つの異なるSTL文字列インスタンスは、同じ基礎となるバッファーを共有できません。したがって、値で渡すと、常に新しいコピーが取得されます。 -パフォーマンスには多少のペナルティがありますが、要件が特別でない限り無視できると思います。
次の場合には、char*
の使用を検討する必要があります。
実際、C++では、char*
は多くの場合、オプション、ファイル名など、固定された小さなWordに使用されます。
C++ std :: string:を使用する場合
char *を使用する場合
ライブラリを作成する場合は、(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 *の場合とまったく同じようにインデックスを付けることができます。