web-dev-qa-db-ja.com

外部フラグなしでループ内でコードを1回だけ実行する方法は?

ループ内の条件をチェックし、最初に満たされたときにコードのブロックを実行したいと思います。その後、ループが繰り返される可能性がありますが、ブロックは無視する必要があります。そのためのパターンはありますか?もちろん、ループの外側でフラグを宣言するのは簡単です。しかし、私は完全にループの中に住んでいるアプローチに興味があります。

この例は私が望むものではありません。ループの外側の定義を取り除く方法はありますか?

bool flag = true;
for (;;) {
    if (someCondition() && flag) {
        // code that runs only once
        flag = false;
    }        
    // code that runs every time
}
11
danijar

これはかなりハッキーですが、アプリケーションのメインループであるとおっしゃっていたように、これは1回限りの関数内にあると想定しているため、次のように機能するはずです。

struct RunOnce {
  template <typename T>
  RunOnce(T &&f) { f(); }
};

:::

while(true)
{
  :::

  static RunOnce a([]() { your_code });

  :::

  static RunOnce b([]() { more_once_only_code });

  :::
}

メビウスの答えのそれほど複雑でないバージョンの場合:

while(true)
{
  // some code that executes every time
  for(static bool first = true;first;first=false)
  {
    // some code that executes only once
  }
  // some more code that executes every time.
}

ブール値で++を使用してこれを記述することもできますが、それは明らかに 非推奨 です。

9
Alec Jacobson

これを書くためのおそらくよりクリーンな方法は、まだ変数がありますが、次のようになります

while(true){
   static uint64_t c;
   // some code that executes every time
   if(c++ == 0){
      // some code that executes only once
   }
   // some more code that executes every time.
 }

staticを使用すると、ループ内で変数を宣言できます。これは、IMHOの方が見栄えがします。毎回実行されるコードでテスト可能な変更が加えられた場合は、変数を削除して次のように記述できます。

while(true){
   // some code that executes every time
   if(STATE_YOUR_LOOP_CHANGES == INITIAL_STATE){
      // some code that executes only once
   }
   // some more code that executes every time.
 }
3
Mobius

このループを1回だけ実行することがわかっている場合は、ループの最後のステートメントとしてbreakを使用してみませんか。

0
Guanxi