C++ 现代C++;

C++ 现代C++;,c++,performance,code-readability,inline-method,C++,Performance,Code Readability,Inline Method,好吧,所以有时候我的“编码大脑”会跳过一个齿轮;偶尔你会听到齿轮的摩擦声。(例如,我每隔一段时间写一次class Foo:Bar{},然后提醒自己这已经不合适了——而且已经很久没有这样做了) 我目前的任务是使用内联方法,在不牺牲速度的情况下提高代码易读性和可维护性,但最近我遇到了一个问题,使我对这种做法产生了疑问 因此,考虑到(公认是人为的)代码如下: double a; double b = 0.0; double c = 0.0; ... // do some stuff here ...

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

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

因此,考虑到(公认是人为的)代码如下:

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能够维护它,那么它必须编写得更像第二个。代码对时间也相当敏感

正如我上面所说,我最近遇到了一个问题。我让我的数学常数
静态常数加倍…
就像一个好的小程序员;但是,当试图以内联方式访问它们时,编译器会轰炸DLL。目标操作系统是Linux,但我正在Windows(Visual Studio 2013)上开发,并希望保持它“跨平台安全”

这个小问题的解决方案;但是,这会影响我的表现吗?考虑到涉及到深奥的数学,可读性是一个严重的问题;但它仍然必须表现良好

更新:

要澄清这一点,请使用更多/不同的——以及更人为的——代码:

\ifndef BUILD\u DLL
#定义DLL\u模式\u declspec(dllimport)
#否则
#定义DLL\u模式\uuu declspec(dllexport)
#恩迪夫
类DLL\u模式贡献概率示例
{
公众:
内联贡献概率示例(双值);
内联贡献概率示例&运算符+=(双值);
私人:
内联无效校验值(双值);
私人:
静态常数双零概率=0.0;
静态常数双保证_PROB=1.0;
双重概率;
私人:
//未实施
贡献概率示例();
};
内联ContrivedProbabilityExample::ContrivedProbabilityExample(双值):概率(值)
{
校验值(值);
}
内联ContrivedProbabilityExample&ContrivedProbabilityExample::运算符+=(双值)
{
校验值(值);
概率=概率+值-(概率*值);
}
内联void ContrivedProbabilityExample::CheckValue(双值)
{
如果(值<零概率| |值>保证概率)
抛出std::range_错误(“嘿,你认为你在做什么?”);
}
这段代码在两个平台上都可以在静态环境下正常工作;它将作为Linux上的共享库工作。当尝试将其用作DLL时,它将在Windows下给出一个错误。唯一的解决方案是将
CheckValue
方法移出行

“old school”
inline
CheckValue
方法的代码替换为调用它的“原样”;很明显,“新学校”是。。。没有什么?(因为编译器显然做了它想做的事情。)

AFIK在DLL下执行此操作的唯一方法是将
CheckValue
移出行。。。这对于时间敏感的代码“老派”来说可能是一个问题(每个调用都保证了函数开销)。这仍然是个问题吗?是否有一种“更好”的方法来保持可读性;e、 g.不要假设每个从事我的代码工作的CS/CE都精通统计


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

您想使用
constep
,类似于:

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

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

不确定你的问题是什么,但是关于这个:

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();
};
类DLL\u模式贡献概率示例
{
公众:
贡献概率示例(双值)
{CheckValue(value);}
贡献概率示例和运算符+=(双值)
{
校验值(值);
概率=概率+值-(概率*值);
}
私人:
无效校验值(双值)
{
如果(值<零概率| |值>保证概率)
抛出std::range_错误(“嘿,你认为你在做什么?”);
}
私人:
constexpr双零概率=0.0;
constexpr双保证概率=1.0;
双重概率;
私人:
//未实施
贡献概率示例();
};

如果您的问题是确保性能,最好的处理方法是插入一个
断言()
来执行健全性检查

应该由调用方来确保将正确的值传递给概率函数(并且应该有很好的文档记录),如果某个调用方不这样做,
assert()
将帮助您进行调试。但是,当您发送代码时,您可以简单地停用所有断言,从而消除检查的性能损失


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

在同一行中定义三个变量,而不初始化其中任何一个?我不建议这样做。除此之外,我认为你的问题太宽了。我认为你应该把重点放在解释你的确切问题上。请记住,
inline
更像是对编译器的建议,编译器很容易忽略这个建议。此外,我认为现代编译器上的默认优化非常好,有时您甚至可以从缺少该关键字中获益。John-您是否尝试过
constexpr
?它旨在解决(或至少有助于)非整数常量的ODR问题。@ecatmur无论如何,我的观点是,如果您编写代码是为了提高性能,您可能不应该太依赖
inline
关键字,在我看来,阅读编译器文档比使用该关键字要好得多。
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();
};