2016-07-26 5 views
1

私は次のような条件を持っています。この条件は比較的頻繁に呼び出されるため、1回だけトリガーになるようにします。毎回falseにするという考え方が気に入らないので、bool条件が真であるので、論理ANDとORの順序とポストインクリメント演算子を利用しようとしました。しかし、それは私がそれが期待したことをしないで動作するように見えます。では、この行のポストステートスイッチを作成する方法はありますか?boolで "ポストスイッチ"のような操作をする方法はありますか?

firstTitleNotSetである:

bool firstTitleNotSet; 

if (titleChangedSinceLastGet() || (p_firstTitleNotSet && p_firstTitleNotSet++)) 

アイデアは最初の部分は、一次トリガーであり、第二は、初回のみをトリガしなければならないトリガーであることです。

私は簡単に今までに条件ブロックが呼び出されたときに、それは偽の再割り当てされるように私はこれが好きではない

if (titleChangedSinceLastGet() || p_firstTitleNotSet) 
{ 
    firstTitleNotSet = false; 
    //... 
} 

を行うことができますが。

したがって、ブールの値をtrueからfalseに変更する "ポスト変更"の方法がありますか?私はこれが他の方法で動作することを知っていますが、これはメソッドの利点を無効にします。ほとんどの時間が真のトリガーであるため、次のチェックをスキップします。

注:このような考慮事項を作成する理由は、このブロックが頻繁に呼び出されるため、消費されたランタイムを最適化するためです。

if (titleChangedSinceLastGet() || 
    (p_firstTitleNotSet ? ((p_firstTitleNotSet=false), true):false)) 

代替構文は次のようになります:

if (titleChangedSinceLastGet() || 
    (p_firstTitleNotSet && ((p_firstTitleNotSet=false), true))) 

どちらか一つがやや醜い

+0

'(std :: exchange(p_firstTitleNotSet、false)== true)'のようなものを試しましたか? – KABoissonneault

+0

@ KABoissonneault:いいえ、私はそれを知らないと認めなければなりません。しかし、私はそれが実際に仕事をするかどうかはまだはっきりしていません。私には、価値を残しているすべての呼び出しに対して実行される方法、私が必要としていることとは全く異なる方法があります。 – dhein

+3

これは無駄なマイクロ最適化のようですが、条件が真であるたびにこの単一の割り当てがパフォーマンスに顕著な差をつけることはありますか? – SirGuy

答えて

2

さて、あなたのような何かを行うことができます。 、あなたの提案の代替で

if (titleChangedSinceLastGet() || p_firstTitleNotSet) 
{ 
    p_firstTitleNotSet = false; 
    //... 
} 

p_firstTitleNotSet条件が入力された場合でも、どんなをfalseにリセットされなかっ取得しているという事実を司教職:これはあなたの他の代替と同じませであること、しかし、注意してくださいtitleChangedSinceLastGet()です。動作するはず

+0

私は最後のbeeingが他のものとまったく同じではないことを認識していますが、私の場合は両方とも必要な動作に適合します。とにかく、あなたの2番目のブロックは私が達成しようとしているEAXACTLYです。私はそれが醜いことをあなたとaggree。しかし、この場合、より読みやすいコードから同じパフォーマンス上の利点を得るには、他にもいくつかの方法がありますか? – dhein

+0

'if'の中でフラグを' false'に明示的にリセットする場合は、それを使用してください。パフォーマンスの差が実際に測定可能な場合、私は驚くだろう。現代の、深いパイプラインのCPUは、彼らがやることにかなり優れています。 –

+0

構文を説明するか、 '((p_firstTitleNotSet = false)、)'セグメントに含まれる概念を引用できますか?私はかつてそれを見たことがない。 – rtmh

0

:それらの残りの部分でb=0ながら、最初の反復b=2

int b = 1; 
if (titleChangedSinceLastGet() || (b=b*2%4)) 

int firstTitleSet = 0; 
if (titleChangedSinceLastGet() || (!firstTitleSet++)) 

あなたが行うことができますオーバーフローを避けたい場合。このような状況で

+0

これは、整数オーバフローの場合に正しいものとなるために、プログラマが何分かの手間をかけることになります。整数オーバフローは未定義の動作ではないと言わずに、アイデアも思いつきました。 – dhein

+0

@ザビス編集された答えを見てください。 –

+0

再度ポイントがありません。これは、必要に応じて動作することは事実です。しかし、これはパフォーマンスをさらに悪化させます。私は、実行ごとに1つのブールアラインメントを最適化しようとしていることを意味します。例として、2つの整数演算+ 1つの整数アラインメントを実行ごとに追加します。これは最適化のポイントがありません。それ以外はUBのように、「オーバーフローを避けることを望む」ことに注意してください。 – dhein

0

、私は通常の書き込み:

bool firstTitleNotSet = true; 

if (titleChangedSinceLastGet() || firstTitleNotSet) 
{ 
    if (firstTileNotSet) firstTitleNotSet = false; 
    //... 
} 

第2の比較可能性が高い、コンパイラによって最適化されること。

しかし、あなたはポストインクリメント演算子を優先している場合:iterationCountオーバーフローが、同じあなたは、ポストインクリメントをしたbool firstTitleNotSetの真のであれば、これは問題になること

int iterationCount = 0; 
if (titleChangedSinceLastGet() || iterationCount++ != 0) 
{ 
    //... 
} 

注意を。

コードの可読性とメンテナンス性の観点から、前者をお勧めします。あなたのコードのロジックが健全な場合は、たとえそれがあなたにとって魅惑的ではなくても、コンパイラを使って最適化を行うことができます。

+0

あなたの最初の例は、毎回チェックされる条件があるので、私がやっていることがさらに悪くないならば、私が避けたいものです。そして、2番目の例では、そのような場合に整数オーバーフローを処理しないと問題が解決されます。 – dhein

+0

あなたのモチベーションがコード優雅さかランタイム性能かどうかはわかりませんが、後者のように聞こえます。おそらく実行時のパフォーマンスに恩恵を与えない方法でソースコードを最適化しようとしている可能性があります。このレベルの詳細が気になる場合は、コードを逆アセンブルしてコンパイラが実際に生成しているものを確認することをお勧めします。たとえ分解しても、深くパイプライン化された最新のプロセッサでのパフォーマンスは正確には分かりませんが、真実に近づくでしょう。 –

+0

私はそれについては不明であり、編集でそれを明確にしました。しかし、私の最初の例は、Sam Varshのように、彼の答えでこれを完成させていることに注意してください。コンパイラが正しい言語を正しく書いたコードを実装していれば、それは決して洗練されていません。ランタイムの結果にはさらに少ない回数が必要です。コンパイラは間違った解釈をするか、別のレベルにあります。しかし、私はここで何も考慮しようとしません。 – dhein

1

if内部or内部の三項演算子はただ自分の文に業務を移動することになる内部の割り当てよりも読みやすい方法:

bool needsUpdate = titleChangedSinceLastGet(); 
    if(!needsUpdate && firstTitleSet) 
    { 
     needsUpdate = true; 
     firstTitleSet = false; 
    } 

    if(needsUpdate) 
    { 
     //... 
    } 

これは以下の非常に類似したアセンブリを生成する可能性があります3進演算子はほとんどの場合、if文のまわりの文法的な砂糖です。

は私が GCC Explorer次のコードを与え、これを実証する:

にextern最初のブール値。 bool changed();

であり、生成されたアセンブリは、最適化後に生成されたアセンブリにわずかな差しかなかった。確かに自分自身を見てください。

しかし、これはパフォーマンス上の顕著な違いを起こす可能性は低く、これはもっと興味深いものです。私の意見で

if(titleChangedSinceLastUpdate() || firstTitleSet) 
    { 
     firstTitleSet = false; 
     //... 
    } 

は、(少なくとも)も同様に良いオプションです。

上記の関数のアセンブリをこれと比較して、さらに比較することができます。

bool f3() 
{ 
    if(changed() || first) 
    { 
    first = false; 
    return true; 
    } 
    return false; 
} 
+0

私がここに来て、アドベンチャーは本当に小さいです、私はあなたの2番目の例である前に持っていたアイデアにとどまります。条件付き条件付きの最初の例は常に悪化するでしょうか? – dhein

+0

@ Zaibisこれは、 "if"メソッドの中の 'または'の内部の三項内部の代入と非常によく似たアセンブリを生成する1ドルと賭けるでしょう。コンパイラの三項演算子と 'if'文の違いの点からは、それを解析する方法があります。 – SirGuy

+0

あなたの答えでこれをelaboarteできる場合は、少なくとも私からupvoteを得るだろう。 – dhein