现代C ++中的内联方法和代码可读性

时间:2014-07-02 15:42:39

标签: c++ performance code-readability inline-method

好吧,有时我的编码大脑"跳过一个装备;偶尔你会听到齿轮磨损。 (例如,我每隔一段时间写一次class Foo : Bar {},然后再提醒自己“不再适合 - 并且还没有时间。” / p>

我目前的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)并且希望保持它"跨平台安全"。

解决这个小问题is to take them out-of-line;但是,这会伤害我的表现吗?鉴于所涉及的深奥数学,可读性是一个严重的问题;但它仍然必须表现良好。

更新

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

#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上的共享库。尝试将其用作DLL时,它会在Windows下出错。唯一的解决方案是将CheckValue方法移出线外。

&#34;老派&#34; inline已将CheckValue方法的代码替换为&#34; as-is&#34;从哪里调来;显然&#34;新学校&#34;内联确实......什么都没有? (因为无论如何编译器显然都会做它想要的。)

AFIK在DLL下进行此项工作的唯一方法是将CheckValue移出线外...这可能是时间敏感代码的问题&#34;老派&#34; (每次通话都是保证功能开销)。这还是个问题吗?是否有更好的&#34;保持这种可读性的方法;例如不要假设每个在我的代码上工作的CS / CE都会精通统计数据吗?

注意:这是跨平台的,所以&#34;编译器&#34;可能不是一个有意义的短语。

3 个答案:

答案 0 :(得分:1)

您想使用constexp,例如:

inline constexpr double ProbabilisticOr(double b, double c)
{
    // Skip the Sanity checks
    return b + c - (b * c);
}
然后你可以自由地做以下事情:

static const double a = ProbabilisticOr(b, c);

答案 1 :(得分: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();
};

答案 2 :(得分:0)

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

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

没有什么比不检查更快,这就是为什么在C / C ++中解除引用指针永远不会安全,永远不会。