最近C++でC文字列を使用する正当な理由はありますか?私の教科書では、いくつかの点で例としてそれらを使用していますが、std::stringを使用するだけの方が簡単だと実感しています。
18 に答える
私がそれらを使用しなければならなかった唯一の理由は、Cスタイルの文字列を使用するサードパーティのライブラリとインターフェイスするときです。パフォーマンス上の理由からCスタイルの文字列を使用するという難解な状況もあるかもしれませんが、多くの場合、インライン化や特殊化などにより、C++文字列でメソッドを使用する方が高速です。
この種のAPIを使用する場合、多くの場合このメソッドを使用できますがc_str()
、返されるchar *はconstであり、そのポインターを介して文字列を変更しないように注意する必要があります。このような状況でも、代わりにvector <char>を使用でき、少なくともメモリ管理が簡単になるという利点があります。
さらにいくつかのメモリ制御メモ:
C 文字列は POD 型であるため、アプリケーションの読み取り専用データ セグメントに割り当てることができます。名前空間スコープで定数を宣言および定義すると、コンパイラは、各定数のコンストラクターを呼び出すstd::string
前に実行される追加のコードを生成します。アプリケーションに多くの定数文字列がある場合 (たとえば、定数文字列を使用する C++ コードを生成した場合)、この状況では C 文字列が望ましい場合があります。main()
std::string
の一部の実装ではstd::string
、SSO (「短い文字列の最適化」または「小さな文字列の最適化」) と呼ばれる機能がサポートstd::string
されています。クラスには、特定の長さまでの文字列のストレージが含まれています。これにより、サイズが増加しますが、多くのstd::string
場合、フリー ストアの割り当て/割り当て解除の頻度が大幅に減少し、パフォーマンスが向上します。の実装がstd::string
SSO をサポートしていない場合std::string
でも、スタック上に空を構築すると、フリー ストアの割り当てが実行されます。その場合、スタックに割り当てられた一時的な C 文字列を使用すると、文字列を使用するパフォーマンスが重要なコードに役立つ場合があります。もちろん、これを行うときに自分の足を撃たないように注意する必要があります。
それが彼らが多くのAPI/ライブラリから来ている方法だからですか?
コードにいくつかの文字列定数があるとしましょう。これはかなり一般的なニーズです。これらをC++オブジェクトとして定義するよりもC文字列として定義する方が適切です。軽量でポータブルなどです。これらの文字列をさまざまな関数に渡す場合は、これらの関数がC文字列を必要とせずにC文字列を受け入れると便利です。 C++文字列オブジェクト。
もちろん、文字列が可変である場合は、C++文字列オブジェクトを使用する方がはるかに便利です。
関数に定数文字列が必要な場合、プログラムが std::string、CString、EString などを使用している場合でも、'const char*' (または const wchar_t*) を使用することを好みます。
大規模なコード ベースには文字列のソースが多すぎて、呼び出し元が文字列を std::string として保持し、「const char*」が最小公分母であることを確認できません。
多くの基本的な関数がまだ引数としてそれらを期待するか、それらを返すため、教科書は古い学校の C 文字列を特徴としています。さらに、メモリ内の文字列の基になる構造についての洞察も得られます。
メモリ制御。私は最近、大規模なマルチスレッド アプリケーションで、サイズが約 200 ~ 300 MB の文字列 (実際にはデータベースからのブロブ) を処理する必要がありました。文字列のもう 1 つのコピーが 32 ビット アドレス空間をバーストする可能性がある状況でした。文字列のコピーがいくつ存在するかを正確に知る必要がありました。私は STL エバンジェリストですが、余分なメモリや余分なコピーが割り当てられないことを保証できるので、char * を使用しました。どのくらいのスペースが必要なのかがよくわかりました。
それとは別に、標準の STL 文字列処理は、文字列処理/解析のためのいくつかの優れた C 関数を見逃しています。ありがたいことに、std::string には内部バッファーへの const アクセス用の c_str() メソッドがあります。printf() を使用するには、依然として char * を使用する必要があります (C でこれまでで最も便利な関数の 1 つである (s)printf のような機能を含めないという C++ チームのクレイジーなアイデアです。boost::format がすぐに STL に含まれます。
いくつかの投稿は記憶の懸念に言及しています。これはstd::stringを回避する良い理由かもしれませんが、char*はおそらく最良の代替ではありません。それはまだオブジェクト指向言語です。独自の文字列クラスは、おそらくchar*よりも優れています。それはさらに効率的かもしれません-例えば、あなたは小さな文字列の最適化を適用することができます。
私の場合、2GBのファイルから約1GB相当の文字列を取得し、それらを約60フィールドのレコードに詰め込んでから、異なるフィールドで7回ソートしようとしていました。私の前任者のコードはchar*で25時間かかり、私のコードは1時間で実行されました。
C ++コードが「深い」場合(カーネルに近い、Cライブラリに大きく依存しているなど)、std :: stringとの間での多くの変換を回避するために、C文字列を明示的に使用することをお勧めします。他の言語ドメイン(Python、Rubyなど)とインターフェースをとっている場合は、同じ理由でそうする可能性があります。それ以外の場合は、std::stringを使用します。
std::string を認識しないレガシー コード。また、C++11 より前は std::ifstream または std::ofstream を使用してファイルを開くことは、ファイル名への入力として const char* を使用した場合にのみ可能でした。
初期化ルールと考えられるすべての文字列実装をいくつかのプラットフォームでデバッグするのに非常に多くの時間を費やした後、静的文字列を const char* にする必要があります。
悪い char* コードとメモリ リークのデバッグに非常に多くの時間を費やした後、私はすべての非静的文字列を何らかの文字列オブジェクトにすることをお勧めします ... プロファイリングによって、もっと良いことができること、またそうすべきであることが示されるまでは ;-)
1) 「文字列定数」は C 文字列 (const char *) であり、それを const std::string& に変換するのは実行時プロセスであり、必ずしも単純または最適化されているわけではありません。2) fstream ライブラリは、C スタイルの文字列を使用してファイル名を渡します。
私の経験則では、とにかくデータを std::string として使用しようとしている場合は const std::string& を渡し、それ以外の場合は const char * を渡します。
c文字列は、クラスであるというオーバーヘッドを伴いません。
c文字列は、マシンレベルに近いため、通常、コードが高速になる可能性があります。
これは、彼らと一緒に悪いコードを書くことができないということではありません。他のすべての構成と同様に、それらは誤用される可能性があります。
歴史的な理由でそれらを要求する自由な呼びかけがたくさんあります。
c文字列とstl文字列の使用方法を学び、必要に応じてそれぞれを使用します。
操作中の文字列を格納するためのヒープの余裕がなく、文字列バッファの決定論的な事前割り当てが必要な、ほとんどの組み込みプラットフォームなどのアプリケーションの場合。
使用しているライブラリによって異なります。たとえば、MFCを操作する場合、Windows API のさまざまな部分を操作するときに CString を使用する方が簡単なことがよくあります。また、Win32 アプリケーションでは std::string よりもパフォーマンスが優れているようです。
ただし、std::string は C++ 標準の一部であるため、移植性を高めたい場合は std::string を使用してください。
char*
選択肢が与えられた場合、通常、 C++ 文字列( ) よりもプリミティブ C 文字列 ( ) を選択する理由はありませんstd::string
。ただし、多くの場合、選択の余地はありません。たとえば、std::fstream
歴史的な理由から、 のコンストラクターは C 文字列を取ります。また、C ライブラリ (ご想像のとおりです!) は C 文字列を使用します。
独自の C++ コードでは、 の関数をstd::string
使用して、必要に応じてオブジェクトの C 文字列を使用および抽出するのが最適です。c_str()
std::string
STL文字列は確かにはるかに使いやすく、使用しない理由はわかりません。
Cスタイルの文字列のみを引数として取るライブラリと対話する必要がある場合は、いつでも文字列クラスのc_str()メソッドを呼び出すことができます。
それを行う通常の理由は、文字列処理でバッファオーバーフローを書くことを楽しむことです。カウントされた文字列は、終了した文字列よりも優れているため、Cの設計者が終了した文字列を使用した理由を理解するのは困難です。その時は悪い決断でした。今は悪い決断です。