如何在C ++中定义pow2宏

时间:2013-12-20 14:40:06

标签: c++ performance macros euclidean-distance

我想对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);
}

3 个答案:

答案 0 :(得分:8)

如果您坚持编写宏,请为变量使用其他名称。但你的宏非常可怕。首先,对于并发调用,它不是线程安全的,因为线程将访问相同的临时变量。此外,大多数宏一般都是非常邪恶的(虽然有一些例外)。

然而,相同(也是性能方面)可以更容易实现(即使支持float以及带有operator*功能模板的其他类型:

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

如果你想要一个宏,那么#define pow2C square sarcasm sign )。

答案 1 :(得分:5)

这是定义宏的一种可怕方式!您不应该将变量作为计算的一部分引入。相反,试试这个:

#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;
}

现在你只进行一次减法计算!

答案 2 :(得分:2)

  

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

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

如果您仍然坚持,则您输入的错误does not exist in this code

但是,你的宏内容有问题,它会读取和写入表达式中的单个变量。结果未定义:

#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实用程序函数,但这里不需要宏。