1

次のコードを使用して、関数の配列引数のサイズを取得できることを知っている場合と知らない場合があります。

template<typename DataType, size_t SIZE>
void SortingAlgorithm(DataType (&array)[SIZE])
{
  ...
  return;
}

ここで、SIZEを使用して配列内の要素の数を表すことができるため、関数を使用するプログラマーは、長さを明示的に渡さずに配列を引数として渡すことができます。たとえば、プログラマーはこれを行うことができます。

SortingAlgorithm( arrayToBeSorted ); //the length is not passed here, which is fine

反復スタイルで比較的簡単に実装できるアルゴリズムの場合、これは問題ありません。しかし、私は再帰的な他のアルゴリズムでこれを実行しようとしました。それぞれのコードは次のようになります。

template<typename DataType, size_t SIZE>
void SortingAlgorithm(DataType (&array)[SIZE])
{
  DataType newArray[SIZE];
  memcpy(newArray,array, SIZE);  //copy to a new array
  SortingAlgorithm( newArray );
  ...
  return;
}

しかし、これは、プログラムが異なる引数型を予期し、型変換が失敗し、newArray配列のSIZE指定子を複数回型キャストしようとしたことを示すたびにエラーをスローし、プログラムは失敗します。ただし、次のように再帰呼び出しを行う前に、実際の値を使用してnewArrayのサイズを定義しても、これらのエラーは発生しません。

DataType newArray[10]; //arbitrary number, but the compiler accepts this.

可変サイズの配列がエラーを引き起こすのはなぜですか?また、入力として配列を受け入れるが、関数呼び出し内で毎回配列の長さを決定できるため、引数として配列の長さを必要としない再帰的アルゴリズムを実装する方法はありますか?

4

4 に答える 4

7

サイズを取るヘルパー関数を作成します。それは他の関数によって内部的に使用でき、誰もそれについて知る必要はありません。例えば:

template<typename DataType>
void SortingAlgorithm_helper(DataType * ptr, size_t size)
{
    ...
    SortingAlgorithm_helper(ptr + 1, size - 1);
    ...
}

template<typename DataType, size_t SIZE>
void SortingAlgorithm(DataType (&array)[SIZE])
{
    ...
    SortingAlgorithm_helper(newArray,SIZE);
    ...      
}

あなたのコメントにより、ベクターへの切り替えを検討しています。ここで選択する必要はありません。両方を処理するために、コードをより汎用的にすることができます。ヘルパー関数にポインターとサイズを渡す代わりに、範囲を指定する 2 つの反復子を渡します。次に、メイン関数を変更して、任意のコンテナーを受け入れるようstd::beginstd::endします。

template<typename Iterator>
void SortingAlgorithm_helper(Iterator first, Iterator last)
{
    ...
    SortingAlgorithm(++first, last);
    ...
}

template<typename Container>
void SortingAlgorithm(Container & c)
{
    ...
    SortingAlgorithm_helper(std::begin(c), std::end(c));
    ...
}

これは、組み込みの配列 、std::vectorstd::arrayおよびを処理する必要がありstd::dequeます。イテレータで実行される操作を双方向 (++ および --) に制限する場合は、std::list同様に処理する必要があります。

于 2012-11-09T20:44:19.177 に答える
4

これをしないでください。代わりに、次のオプションのいずれかを使用します。

  • 配列の代わりにstd::vector(メソッドを持っている)を使用します。size()
  • 配列のサイズを追加の引数として関数に渡します。

再帰アルゴリズムに関しては、要素を新しい配列にコピーするだけではいけません。時間がかかります。

代わりに、処理する配列の部分の先頭と末尾に 2 つのポインターを渡します (STL アルゴリズムのしくみを見てくださいstd::sort。コンテナーを使用せず、代わりに 2 つのイテレーターを使用します)。

ただし、これは実際には使用しているアルゴリズムの詳細に依存することに注意してください。一部のアルゴリズムでは実際に明示的なコピーが必要になる場合がありますが、可能な場合は避ける必要があります。

于 2012-11-09T20:40:33.210 に答える
1

テンプレートはコンパイル時にコードを生成します。10 のような値を指定すると、使用する値がわかっているため、コードを生成できます。コンパイル時に決定できないもの (実行時にのみ値を持つ変数など) を指定すると、コードを生成するときに使用する値がわからないことを意味します。

于 2012-11-09T20:43:42.890 に答える
0

コンパイラは、実行時ではなく、コンパイル時にサイズを把握する必要があります。私のコンパイラはあなたのコードを記述どおりに受け入れますが、どうやらあなたのコードはサイズを把握できません。次のように明示的にサイズを指定できます。

SortingAlgorithm<DataType, SIZE>( newArray );.

そのコード行の両方のバージョンが私のコンパイラで動作します。

于 2012-11-09T20:50:41.690 に答える