1

compase.cpp コードを読むと、次のことがわかります。

/* We have to ensure that we DON'T use a max macro, since these will typically   */                    
/* lead to one of the parameters being evaluated twice.  Since we are worried    */                    
/* about concurrency, we can't afford to access the m_cRef twice since we can't  */                    
/* afford to run the risk that its value having changed between accesses.        */                    

    template<class T> inline static T ourmax( const T & a, const T & b )                                   
    {
        return a > b ? a : b;       
    } 

「max マクロがパラメーターの 1 つを 2 回評価する」理由がわかりません。

4

2 に答える 2

2

このコードサンプルのような使用法を考えてみましょう。

#define max(a,b) (a>b?a:b)

int main()
{

  int a = 0;
  int b = 1;

  int c = max(a++, b++);

  cout << a << endl << b << endl;
  return 0;

}

意図はおそらく印刷することでしたが12マクロは次のように拡張されます。

int c = a++ > b++ ? a++ : b++;

bは2回インクリメントされ、プログラムはとを出力13ます。

したがって、
場合によっては、マクロに引数として渡される式を複数回評価することができます。

于 2012-05-22T05:07:04.600 に答える
1

Als は差し迫った問題を非常に明確に説明していますが、私には 2 つの大きな問題が見られます。1 つ目は単純です。maxこれは、 で定義された標準関数テンプレートであるため、マクロにすることはできません<algorithm>。(VC++ の場合、NOMINMAXを使用するために定義する必要があります<algorithm>。しかし、標準関数が仕事をするときは常に標準関数を使用することが望ましいので、事実上常にNOMINMAXプリプロセッサの定義に追加し、それで完了する必要があります。)

2 つ目は、コードに関する理解の欠如を示しているため、さらに心配です。コメントは「同時実行性」に言及しており、関数を使用することで同時実行性の問題がないことを示唆しています。これは単に正しくありません。他のスレッド (または共有メモリの場合はプロセス) がいずれかの引数を変更する可能性がある場合、動作は未定義です。特に、書かれているように、コンパイラーは値の 1 つを 2 回読み取る可能性があります。引数は参照です。ただし、どのように記述しても、コンパイラは値を再読み取りできます。そうでない場合でも、アクセスがアトミックであることを保証するものは何もありません。コメントを書いた人は、マルチスレッド コードの基本原則を理解していません。

于 2012-05-22T08:03:53.427 に答える