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 でそれを維持できるようにしたい場合は、2 番目のように記述する必要があります。コードはまた、かなり時間に敏感です。

上で述べたように、私は最近問題に出くわしました。私は自分の数学的定数static const double ...を小さなプログラマーのように作りました。しかし、それらにインラインでアクセスしようとすると、コンパイラは DLL を探し出します。ターゲット OS は 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?");
}

このコードは、両方のプラットフォームの Static で問題なく動作します。Linux では共有ライブラリとして機能します。DLL として使用しようとすると、Windows でエラーが発生します。唯一の解決策は、CheckValueメソッドを行外に移動することです。

「古い学校」ではinlineCheckValueメソッドのコードが呼び出された場所で「そのまま」置換されていました。どうやら「新しい学校」のインラインは...何もしないのですか?(コンパイラはどうやら必要なことに関係なく実行するためです。)

AFIK DLL の下でこれを機能させる唯一の方法は、CheckValueアウトオブラインに移動することです...これは、時間に敏感なコード「古い学校」では問題になる可能性があります (すべての呼び出しは、関数のオーバーヘッドが保証されている/保証されていました)。これはまだ問題がありますか? これを読みやすくする「より良い」方法はありますか。たとえば、私のコードに取り組んでいるすべての CS/CE が統計学に習熟していると仮定しないでください。

注:これはクロスプラットフォームであるため、「コンパイラ」は意味のある表現ではない場合があります。

4

3 に答える 3

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);
于 2014-07-02T15:49:22.777 に答える
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 に答える
0

assert()問題がパフォーマンスの確保である場合、これを処理する最善の方法は、サニティ チェックを実行するためにを挿入することです。

適切な値が確率関数に渡されることを確認するのは呼び出し元の責任である必要があります (十分に文書化する必要があります) assert()。ただし、コードを出荷するときに、すべてのアサートを非アクティブ化するだけで、チェックのパフォーマンス ペナルティを取り除くことができます。

まったくチェックしないよりも速い方法はありません。そのため、C/C++ でポインターを逆参照することは安全ではなく、今後も安全ではありません。

于 2014-07-02T18:31:44.947 に答える