C/C#/C++ で後方ループを実行する最良の方法は何ですか?

確かに少しあいまいですが、これを行うための最もタイポグラフィ的に好ましい方法は

for (int i = myArray.Length; i --> 0; )
{
    //do something
}

C++ では、基本的に、反復子またはインデックスを使用して反復するかどうかを選択できます。単純な配列を使用するか、std::vector を使用するかによって異なります。 、さまざまな手法を使用します。

std::vector の使用

イテレータの使用

C++ では、std::reverse_iterator: を使用してこれを行うことができます

for(std::vector<T>::reverse_iterator it = v.rbegin(); it != v.rend(); ++it) {
    /* std::cout << *it; ... */
}

インデックスの使用

std::vector<T>::size によって返される符号なし整数型 ではない 常に std::size_t .大きくても小さくてもかまいません。これは、ループが機能するために重要です。

for(std::vector<int>::size_type i = someVector.size() - 1; 
    i != (std::vector<int>::size_type) -1; i--) {
    /* std::cout << someVector[i]; ... */
}

符号なし整数型の値はビット数を法として定義されるため、機能します。したがって、 -N を設定している場合 、あなたは (2 ^ BIT_SIZE) -N になります

配列の使用

イテレータの使用

std::reverse_iterator を使用しています 繰り返します。

for(std::reverse_iterator<element_type*> it(a + sizeof a / sizeof *a), itb(a); 
    it != itb; 
    ++it) {
    /* std::cout << *it; .... */
}

インデックスの使用

std::size_t を安全に使用できます sizeof 以降、上記とは対照的にここ 常に std::size_t を返します

for(std::size_t i = (sizeof a / sizeof *a) - 1; i != (std::size_t) -1; i--) {
   /* std::cout << a[i]; ... */
}

ポインターに sizeof を適用して落とし穴を回避する

実際、配列のサイズを決定する上記の方法は最悪です。 a が実際に配列ではなくポインターである場合 (これは非常に頻繁に発生し、初心者は混乱するでしょう)、暗黙のうちに失敗します。より良い方法は、以下を使用することです。これは、ポインターが与えられた場合、コンパイル時に失敗します:

template<typename T, std::size_t N> char (& array_size(T(&)[N]) )[N];

最初に渡された配列のサイズを取得し、次に同じサイズの char 型の配列への参照を返すことを宣言することによって機能します。 char sizeof を持つように定義されています of:1. したがって、返される配列には sizeof が含まれます。 of:N * 1、これは私たちが探しているもので、コンパイル時間の評価のみで実行時のオーバーヘッドはゼロです。

する代わりに

(sizeof a / sizeof *a)

今のようにコードを変更してください

(sizeof array_size(a))

C# で 、Visual Studio 2005 以降を使用している場合は、「forr」と入力して [TAB] [TAB] を押します .これは for に展開されます コレクションを遡るループ。

(少なくとも私にとっては) 間違いやすいので、このスニペットを入れるのは良い考えだと思いました.

そうは言っても、私は Array.Reverse() が好きです / Enumerable.Reverse() 前方を繰り返します より良い - 意図をより明確に述べます。