2

好吧,所以有时我的“编码大脑”会跳过一个齿轮;偶尔你会听到齿轮磨擦的声音。(例如,每隔一段时间我都会class Foo : Bar {}在提醒自己这不再合适之前写信——而且已经很久没有这样做了)。

我目前的 MO 是使用内联方法作为一种在不牺牲速度的情况下提高代码易读性和可维护性的方法,但我最近遇到了一个问题,这让我质疑这种做法。

因此,给定(公认的人为)代码,例如:

double a;
double b = 0.0;
double c = 0.0;
...
// do some stuff here
...
// skip the sanity checks
// Magic Formula. This does what?
a = b + c - (b * c); 
...

我会写:

double a;
double b = 0.0;
double c = 0.0;
...
// do some stuff here
...
// skip the sanity checks
// Oh! It's probability!
a = ProbabilisticOr(b, c);
...
inline double ProbabilisticOr(double b, double c)
{
   // Skip the Sanity checks
   return b + c - (b * c);
}

我现在正在研究的数学相当复杂。如果我想要一个通用的 CS/CE 能够维护它,它必须写得更像第二个。该代码对时间也很敏感。

正如我上面所说,我最近遇到了一个问题。我让我的数学常数static const double ...像一个优秀的小程序员;但是当试图内联访问它们时,编译器会为 DLL 炸毁。目标操作系统是 Linux,但我正在 Windows (Visual Studio 2013) 上开发,并希望保持“跨平台安全”。

解决这个小问题的方法是让它们脱节;但是,这会影响我的表现吗?鉴于所涉及的深奥数学,可读性是一个严重的问题。但它仍然必须表现良好。

更新:

为了澄清,使用更多/不同 - 并且更加人为的 - 代码:

#ifndef BUILD_DLL
#  define DLL_MODE __declspec(dllimport)
#else
#  define DLL_MODE __declspec(dllexport)
#endif


class DLL_MODE ContrivedProbabilityExample
{
public:
   inline ContrivedProbabilityExample(double value);
   inline ContrivedProbabilityExample& operator+=(double value);
private:
   inline void CheckValue(double value);
private:
   static const double ZERO_PROB = 0.0;
   static const double GUARANTEED_PROB= 1.0;
   double probability;

private:
   // Not implemented
   ContrivedProbabilityExample();
};

inline ContrivedProbabilityExample::ContrivedProbabilityExample(double value) : probability(value) 
{
   CheckValue(value);
}

inline ContrivedProbabilityExample& ContrivedProbabilityExample::operator+=(double value)
{
   CheckValue(value);
   probability = probability + value - (probability * value);
}

inline void ContrivedProbabilityExample::CheckValue(double value)
{
   if(value < ZERO_PROB || value > GUARANTEED_PROB) 
      throw std::range_error("Hey, whattaya think you're doing?");
}

此代码在两个平台上的静态中都可以正常工作;它将作为 Linux 上的共享库工作。在 Windows 下尝试将其用作 DLL 时会出错。唯一的解决方案是将CheckValue方法移出线外。

“老派”在调用它的地方“按原样”替换inline了方法的代码;CheckValue显然“新学校”内联确实......什么都没有?(因为编译器显然会做它想做的事。)

AFIK 在 DLL 下使这项工作的唯一方法是移CheckValue出线......这对于时间敏感的代码“老派”来说可能是一个问题(每次调用都是/被保证的函数开销)。这仍然是一个问题吗?有没有“更好”的方法来保持可读性?例如,不要假设每个在我的代码上工作的 CS/CE 都会精通统计?

注意:这是跨平台的,因此“编译器”可能不是一个有意义的短语。

4

3 回答 3

1

You want to use constexp, something like:

inline constexpr double ProbabilisticOr(double b, double c)
{
    // Skip the Sanity checks
    return b + c - (b * c);
}

then you're free to do things like:

static const double a = ProbabilisticOr(b, c);
于 2014-07-02T15:49:22.777 回答
0

如果您的问题是确保性能,则处理此问题的最佳方法是插入一个assert()以执行健全性检查。

应该由调用者来确保将正确的值传递给您的概率函数(并且应该有据可查),并且assert()如果某些调用者没有,它将帮助您调试。但是,当您发布代码时,您可以简单地停用所有断言,从而消除检查的性能损失。

没有什么比根本不检查更快的了,这就是为什么在 C/C++ 中取消引用指针从来都不是安全的,也永远不会安全。

于 2014-07-02T18:31:44.947 回答
0

不知道你的问题是什么,但这个呢:

class DLL_MODE ContrivedProbabilityExample
{
public:
   ContrivedProbabilityExample(double value)
   { CheckValue(value); }

   ContrivedProbabilityExample& operator+=(double value)
   {
       CheckValue(value);
       probability = probability + value - (probability * value);
   }

private:
   void CheckValue(double value)
   {
       if(value < ZERO_PROB || value > GUARANTEED_PROB) 
           throw std::range_error("Hey, whattaya think you're doing?");
   }

private:
   constexpr double ZERO_PROB = 0.0;
   constexpr double GUARANTEED_PROB= 1.0;
   double probability;

private:
   // Not implemented
   ContrivedProbabilityExample();
};
于 2014-07-02T17:52:18.983 回答