std::list
およびstd::vector
は存在しますが、C++で従来のC配列を使用する理由はありますか、それともmalloc
のように避けるべきですか?
C++ 11では std::array
が利用可能です。答えは「はい、配列は避けるべきです」です。 C++ 11より前は、C配列を使用して自動ストレージ(つまり、スタック)に配列を割り当てる必要がある場合があります。
確かに、C++ 11ではstd::array
を使用しますが、実際には静的データのみが対象です。 Cスタイルの配列には、std::vector
よりも3つの重要な利点があります。
動的な割り当ては必要ありません。このため、非常に小さな配列が多数ある可能性が高い場合は、Cスタイルの配列が優先されます。 n次元の点のようなものを言う:
template <typename T, int dims>
class Point
{
T myData[dims];
// ...
};
通常、dims
は非常に小さく(2または3)、T
は組み込み型(double
)になり、最終的にはstd::vector<Point>
数百万の要素。 3倍の数百万の動的割り当ては絶対に望まないでしょう。
静的初期化をサポートします。これは、次のような静的データの問題です。
struct Data { int i; char const* s; };
Data const ourData[] =
{
{ 1, "one" },
{ 2, "two" },
// ...
};
初期化の問題の順序allを回避するため、これはベクトル(およびstd::string
)を使用するよりも望ましい場合がよくあります。実際のコードを実行する前に、データがプリロードされます。
最後に、上記に関連して、コンパイラは初期化子から配列の実際のサイズを計算できます。それらを数える必要はありません。
C++ 11にアクセスできる場合、std::array
は最初の2つの問題を解決するため、最初のケースではCスタイルの配列よりも優先して使用する必要があります。ただし、3番目の問題には対処していません。コンパイラーに初期化子の数に応じた配列の次元を持たせることは、Cスタイルの配列を好む正当な理由です。
「決して」とは決して言わないが、STLの真のデータ構造によってその役割が大幅に減少することに同意する。
また、オブジェクト内へのカプセル化により、このような選択の影響を最小限に抑えるべきだと思います。配列がプライベートデータメンバーである場合、クラスのクライアントに影響を与えることなく、スワップインまたはスワップアウトできます。
動的なメモリ割り当てを使用できない安全性が重要なシステムに取り組んできました。メモリは常にスタック上になければなりません。したがって、この場合、コンパイル時にサイズが固定されるため、配列を使用します。
c++
のarray
は、動的サイズstd::vector
およびstd::list
の固定サイズ高速代替を提供します。 std :: array は、c++11
の追加の1つです。 Cスタイルの配列の集合型セマンティクスを提供しながら、stdコンテナーの利点を提供します。
したがって、c++11
では、必要に応じてstd::array
をベクター経由で使用します。しかし、C++03
のCスタイルの配列は避けたい。
スタックに配列を割り当てるためにstd :: arrayを、ヒープにstd :: vectorを多くの人が指摘していることは知っています。しかし、どちらも非ネイティブのアライメントをサポートしているようには見えません。 SSEまたはVPX命令を使用する(したがって、それぞれ128または256バイトのアライメントが必要です)を使用する任意の種類の数値コードを実行している場合、C配列が最善の方法です。
ほとんどの場合、no、たとえばvectors
に対して生の配列を使用する理由は考えられません。 コードが新しい場合。
ライブラリが配列および生のポインタを予期するコードと互換性を必要とする場合、配列の使用に頼らなければならない場合があります。
静的な少量のデータを保存するのであれば、配列はまだ有用だと思います。
Cスタイルの配列は基本的なデータ構造であるため、使用する方が適切な場合があります。ただし、一般的な場合は、基になるデータの角を丸めるより高度なデータ構造を使用します。 C++を使用すると、非常に興味深く有用なことをメモリで実行できます。その多くは単純な配列で機能します。
配列の唯一の利点(もちろん、必要に応じて割り当て解除を自動的に管理するものでラップされます)std::vector
コンパイラーがC++ 11をサポートし、コンストラクターを移動しない限り、vector
がそのデータの所有権を渡すことができないことを考えることができます。
内部でSTLコンテナーを使用する必要がありますが、異なるモジュール間でこのようなコンテナーへのポインターを渡さないでください。そうしないと、依存関係の地獄に陥ってしまいます。例:
std::string foo;
// fill foo with stuff
myExternalOutputProc(foo.c_str());
非常に良い解決策ですが、そうではありません
std::string foo;
// fill foo with stuff
myExternalOutputProc(&foo);
その理由は、std :: stringはさまざまな方法で実装できるが、cスタイルの文字列は常にcスタイルの文字列だからです。