如何在C++中定义 POW2 宏

how to define a pow2 macro in C++

本文关键字:定义 POW2 C++      更新时间:2023-10-16

我想对pow2C进行如下定义。但是我的编译器显示它(__tmpDouble__)已经定义。请帮我定义它。

#ifndef pow2C
double __tmpDouble__;
#define pow2C(a) ((__tmpDouble__=(a))*(__tmpDouble__))
#endif
.
.
.
inline double calculateDistance(double *x, double *y, int NDims) 
{
    double d = 0;
    for (int i = 0; i < NDims; i++)
    // it is faster to calculate the difference once
       d += pow2C(x[i] - y[i]);
    return sqrt(d);
}

如果坚持要编写宏,请为变量使用不同的名称。但是你的宏非常糟糕。首先,就并发调用而言,它不是线程安全的,因为线程将访问相同的临时变量。此外,大多数宏通常都是非常邪恶的(但也有一些例外)。

但是,可以更轻松地实现相同的(也是性能方面的)(即使使用函数模板支持 float 和其他类型的operator*

template <typename T>
T square(const T &v) {
    return v * v;
}

如果你想要一个宏,那么#define pow2C square讽刺符号)。

这是定义宏的糟糕方法!切勿在计算过程中引入变量。相反,请尝试以下操作:

#define pow2C(a) ((a) * (a))

但是,宏对于这种计算来说很糟糕,因为它们可能效率低下并导致不必要的副作用。例如,如果您编写代码,它将扩展到:

 (x[i] - y[i]) * (x[i] - y[i])

你做了两次减法的地方!

请改用C++模板:

template<class T>
T pow2C(const T &value)
{
  return value * value;
}

现在你只需要做一次减法计算!

我只想计算一次 x[i]-y[i],并将其保存在变量中并使用它。

您已经只计算一次。这一切都毫无意义。

如果您仍然坚持,则代码中不存在您命名的错误

但是,宏的内容确实存在问题,宏读取和写入表达式中的单个变量。结果未定义:

#include <iostream>
#include <cmath>
#include <array>
#ifndef pow2C
double __tmpDouble__;
#define pow2C(a) ((__tmpDouble__=(a))*(__tmpDouble__))
#endif

inline double calculateDistance(double *x, double *y, int NDims) 
{
    double d = 0;
    for (int i = 0; i < NDims; i++)
    // it is faster to calculate the difference once
       d += pow2C(x[i] - y[i]);
    return sqrt(d);
}
int main()
{
    const size_t NUM_DIMS = 3;
    std::array<double, NUM_DIMS> x{{5.0, 6.0, 7.0}};
    std::array<double, NUM_DIMS> y{{1.2, 1.5, 9.0}};
    std::cout << "Distance between x and y is: " << calculateDistance(&x[0], &y[0], NUM_DIMS) << 'n';
}
// g++-4.8 -std=c++11 -Wall -pedantic -pthread main.cpp && ./a.out
// main.cpp: In function 'double calculateDistance(double*, double*, int)':
// main.cpp:16:31: warning: operation on '__tmpDouble__' may be undefined [-Wsequence-point]
//         d += pow2C(x[i] - y[i]);
//                                ^
// Distance between x and y is: 6.22013

所以,真的,我们又回来了,不要这样做


如果您仍然不顾一切地避免两次评估x[i] - y[i]

inline double calculateDistance(double* x, double* y, int NDims) 
{
    double d = 0;
    for (int i = 0; i < NDims; i++) {
       const double diff = x[i] - y[i];
       d += diff * diff;
    }
    return sqrt(d);
}

如果您愿意,您可以将乘法工作传递给另一个inline实用程序函数,但这里不需要宏。