私は自分のコードでベクトル、リスト、文字列、および wstring を執拗に使用しています。代わりに chars と wchars を時々使用することにもっと興味を持つようになるキャッチ 22 はありますか?
基本的に、標準テンプレート ライブラリをサポートする環境で作業する場合、プリミティブ型を使用した方が実際に優れている場合はありますか?
STL クラス (ベクトル、文字列など) に固執します。それらはより安全で、使いやすく、生産性が高く、メモリ リークが発生する可能性が低く、少なくとも DEBUG 時 (Visual C++) に境界の追加のランタイム チェックを行います。
次に、パフォーマンスを測定します。ボトルネックが STL クラスにあることがわかった場合は、C スタイルの文字列と配列の使用法に移行します。
私の経験から、ベクトルまたは文字列の使用がボトルネックになる可能性は非常に低いです。
99% の確率で、標準ライブラリの実装の 99% で、std::vectors は十分に高速であり、それらを使用することで得られる利便性と安全性は、わずかなパフォーマンス コストを上回るものであることがわかります。
ベアメタル コードが本当に必要な非常にまれなケースでは、ベクターを C スタイルの配列のように扱うことができます。
vector <int> v( 100 );
int * p = &v[0];
p[3] = 42;
C++ 標準では、ベクトルが連続して割り当てられることが保証されているため、これが機能することが保証されています。
文字列に関しては、便利な要因がほとんど圧倒的になり、パフォーマンスの問題はなくなる傾向があります。C スタイルの文字列にこだわると、strlen() のような関数の使用に戻ることになりますが、これは本質的に非常に非効率的です。
リストに関しては、独自の実装であろうと標準であろうと、リストを使用する前に 2 回、おそらく 3 回考える必要があります。コンピューティングの問題の大部分は、ベクトル/配列を使用してより適切に解決できます。リストが文献に頻繁に登場する理由の大部分は、リストが教科書やトレーニング コースの作成者がポインタと動的割り当てを一度に説明するために使用できる便利なデータ構造であるためです。私はここで、元トレーニング コース ライターとして話します。
1 つの問題は、要素にアクセスするときのオーバーヘッドです。ベクトルと文字列を使用して要素にインデックスでアクセスする場合でも、最初にバッファー アドレスを取得してからオフセットを追加する必要があります (手動では実行しませんが、コンパイラーはそのようなコードを出力します)。生の配列では、すでにバッファアドレスを持っています。この追加の間接化は、場合によってはかなりのオーバーヘッドにつながる可能性があり、パフォーマンスを改善する必要がある場合はプロファイリングの対象となります。
リアルタイムの応答が必要ない場合は、このアプローチをそのまま使用してください。それらは文字よりも安全です。
自分で何かを行うことで、パフォーマンスやメモリ使用量が向上するシナリオに遭遇することがあります (たとえば、std::string には通常、約 24 バイトのオーバーヘッドがあり、std::string 自体のポインターには 12 バイトがあり、動的に割り当てられた部分のヘッダー ブロック)。
私は、std::string から const char* への変換が顕著なメモリ (数十 MB) を節約するプロジェクトに取り組んできました。これらのプロジェクトは、あなたが典型的と呼ぶようなものではないと思います。
ああ、STL を使用するとコンパイル時間がかかり、ある時点でそれが問題になる可能性があります。プロジェクトの結果、リンカに渡されるオブジェクト ファイルが GB を超える場合は、そのうちのどれだけがテンプレートの肥大化であるかを検討する必要があります。
デフォルトのメモリ割り当て手法は、ベクトル用のバッファであり、文字列は、現在割り当てられているメモリが使い果たされるたびに 2 倍の量のメモリを割り当てるものだと思います。これは無駄になる可能性があります。もちろん、カスタムアロケータを提供できます...
考慮すべきもう 1 つのことは、スタックとヒープです。静的サイズの配列と文字列はスタックに置くことができます。または、少なくともコンパイラがメモリ管理を処理します。新しいコンパイラは、関連する C99/C++0x 機能を提供する場合、動的サイズの配列も処理します。ベクトルと文字列は常にヒープを使用するため、非常に厳しい制約がある場合、パフォーマンスの問題が発生する可能性があります。
経験則として、速度/メモリのオーバーヘッドでプロジェクトに悪影響を与えない限り、既にあるものを使用してください...おそらく、99% のものについて、STL が提供するクラスが時間と労力を節約し、プロジェクトにほとんどまたはまったく影響を与えないことがわかります。アプリケーションのパフォーマンス。(つまり、「時期尚早の最適化を避ける」)
文字列のメモリ オーバーヘッドが問題になっているいくつかのプロジェクトに取り組んできました。
アプリケーションをどのようにスケーリングする必要があるかを事前に検討する価値があります。無制限の数の文字列を格納する必要がある場合はconst char*
、グローバルに管理された文字列テーブルに s を使用すると、大量のメモリを節約できます。
ただし、特に理由がない限り、STL 型を使用するのが一般的です。