6

すでに世界中で何度も議論されてきた非常に古い議論であることを私は知っています. しかし、現在、特定のケースで静的配列と動的配列の間で別の方法ではなく、どの方法を使用するかを決定するのに苦労しています。実際、私は C++11 を使用しておらず、静的配列を使用していたでしょう。しかし、どちらにも同等の利点がある可能性があるため、今は混乱しています。

最初の解決策:

template<size_t N>
class Foo
{
    private:
        int array[N];

    public:
        // Some functions
}

2番目の解決策:

template<size_t N>
class Foo
{
    private:
        int* array;

    public:
        // Some functions
}

2 つには独自の利点があるため、たまたま選択することはできません。

  • 静的配列は高速であり、メモリ管理についてはまったく気にしません。
  • メモリが割り当てられていない限り、動的配列は何も重み付けしません。その後、それらは静的配列よりも使いにくくなります。しかし、C++11 以降では、静的配列では使用できないムーブ セマンティクスから大きな利点を得ることができます。

良い解決策は 1 つではないと思いますが、アドバイスを得るか、それについてどう思うか知りたいです。

4

3 に答える 3

5

私は実際には「場合による」には同意しません。オプション 2 は使用しないでください。translationtime 定数を使用する場合は、常にオプション 1 または std::array を使用してください。あなたがリストした利点の 1 つは、動的配列は割り当てられるまでは何の重みも持たないということですが、実際には恐ろしい、大きな欠点であり、強調して指摘する必要があります。

複数の構築フェーズを持つオブジェクトを使用しないでください。決して、決して。それは、いくつかの大きな入れ墨を通して記憶にコミットされたルールであるべきです. 絶対にしないでください。

完全に死んでいないにもかかわらず、まだ完全に生きていないゾンビオブジェクトがある場合、それらの存続期間を管理する複雑さは指数関数的に増大します。すべてのメソッドが完全に生きているか、生きているふりをしているだけかをチェックする必要があります。例外の安全性には、デストラクタで特別なケースが必要です。1 つの単純な構築と自動破棄の代わりに、N 個の異なる場所 (# メソッド + dtor) でチェックする必要がある要件を追加しました。また、チェックしてもコンパイラは気にしません。また、他のエンジニアはこの要件をブロードキャストしないため、チェックせずに変数を使用して安全でない方法でコードを調整する可能性があります。そして今、これらのメソッドはすべて、オブジェクトの状態に応じて複数の動作を行うため、オブジェクトのすべてのユーザーが何を期待するかを知る必要があります。 ゾンビはあなたを台無しにします(コーディング)人生。

代わりに、プログラムに 2 つの異なる自然寿命がある場合は、2 つの異なるオブジェクトを使用してください。ただし、これはプログラムに 2 つの異なる状態があることを意味するため、ステート マシンが必要です。一方の状態にはオブジェクトが 1 つだけあり、もう一方の状態には両方のオブジェクトがあり、非同期イベントで区切られています。2 つのポイント間に非同期イベントがない場合、それらがすべて 1 つの関数スコープに収まる場合、分離は人為的であり、単一フェーズの構築を行う必要があります。

変換時間のサイズを動的割り当てに変換する唯一のケースは、サイズがスタックに対して大きすぎる場合です。次に、メモリの最適化に進みます。最適なものを確認するには、メモリとプロファイリング ツールを使用して常に評価する必要があります。オプション 2 は決して最善ではありません (これはネイキッド ポインターを使用するため、ここでも RAII と自動クリーンアップと管理が失われ、不変条件が追加され、コードがより複雑になり、他のユーザーが簡単に解読できるようになります)。ベクトル (ビットマスクで提案されている) が適切な最初の考えですが、ヒープ割り当てコストが時間内に気に入らない場合があります。その他のオプションは、アプリケーションのイメージ内の静的スペースである場合があります。ただし、これらは、メモリの制約があると判断した場合にのみ考慮する必要があり、そこから何をすべきかは、実際の測定可能なニーズによって決定する必要があります。

于 2012-04-30T15:52:39.523 に答える
4

どちらも使用しないでください。std::vectorほとんどの場合、使用したほうがよいでしょう。他の場合、それはなぜ不十分であるかという理由に大きく依存し、std::vectorしたがって一般的に答えることができません!

于 2012-04-29T22:59:45.343 に答える
4

現在、特定のケースでどちらを使用する必要があるかを判断するのに問題があります。

特定のコンテキストに最適なソリューションを決定するには、オプションをケースバイケースで検討する必要があります。つまり、一般化することはできません。1 つのコンテナーがすべてのシナリオに理想的である場合、もう 1 つのコンテナーは時代遅れになります。

既に述べたようstdに、独自の実装を作成する前に実装を使用することを検討してください。

詳細:

固定長

  • 消費するスタックの量に注意してください。
  • 動的にサイズ変更されたコンテナとして扱う場合、より多くのメモリを消費する可能性があります。
  • 高速コピー。

可変長

  • 再割り当てとサイズ変更にはコストがかかる場合があります。
  • 必要以上のメモリを消費する可能性があります。
  • 素早い動き。

より良い選択には、要素タイプの作成、コピー、割り当てなどの複雑さを理解することも必要です。

また、std実装を使用する場合は、実装が異なる場合があることに注意してください。

最後に、実装の詳細を抽象化し、サイズとコンテキストに基づいて適切なデータ メンバーを動的に選択するこれらの型のコンテナーを作成できます。つまり、一般的なインターフェイスの背後にある詳細を抽象化します。これは、機能を無効にしたり、一部の操作 (コストのかかるコピーなど) をより明確にしたりする場合にも役立ちます。

つまり、特定のシナリオに最適なコンテナーの種類を決定するには、種類と使用法についてよく理解し、プログラムのいくつかの側面を測定する必要があります。

于 2012-04-30T00:33:21.783 に答える