1

阅读 combase.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;       
    } 

我不明白为什么“最大宏导致参数之一被评估两次”?

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;

}

目的可能是打印1and 2,但宏扩展为:

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

b增加两次,程序打印13.

因此,
在某些情况下,作为参数传递给宏的表达式可以被多次计算。

于 2012-05-22T05:07:04.600 回答
1

尽管 Als 已经非常清楚地解释了当前的问题,但我看到了两个更大的问题。第一个很简单:max不能是宏,因为它是标准函数模板,定义在<algorithm>. (在 VC++ 的情况下,您需要定义NOMINMAX才能使用<algorithm>. 但由于在完成工作时总是最好使用标准函数,因此您实际上应该始终添加NOMINMAX到您的预处理器定义中,并完成它。)

第二个更令人担忧,因为它表明对代码缺乏理解。评论中提到了“并发”,并建议通过使用该函数,不存在并发问题。这是完全不正确的。如果任何其他线程(或进程,在共享内存的情况下)可以修改任一参数,则行为未定义。特别是,如所写,编译器可能会读取其中一个值两次;论据是参考。但无论你如何编写它,编译器都可以重新读取这些值;即使没有,也无法确保访问是原子的。写评论的人不懂多线程代码的基本原理。

于 2012-05-22T08:03:53.427 回答