2012-01-08 13 views
2

私は再帰的な計算を行うことを目的とした関数を持っています。私の関数が再帰的にプログラムされていると、計算に時間がかかりすぎます。したがって、中間結果を配列に格納してメモを実行します。私のプログラムの実行中 名前空間の変数を隠すC++

は、私はので、私は正しい値を持つ配列全体を埋め setup(double x)機能を持っているなどのパラメータ (10,0)(5,5)(2,4)で関数を呼び出すことができます。私はその後、さらに計算することなく配列値のいずれかにアクセスできます。私は xの変更を setup()に再度呼び出すまで待つだけです。

私はこれをC++でどのように実装するのかと思います。私は関連するオブジェクトを作成する必要がないので、クラスを使用することは私には意味がありません。私は名前空間で関数をうまく実装しましたが、まだ問題があります。名前のない名前空間を使用しても、私の関数で使用される配列は可視であり、関数の名前空間の外側から変更することができます。名前空間のヘッダファイルをインクルードすると、それはです。

私のコード:

FunctionWrapper.h

namespace FunctionWrapper{ 
     namespace{ 
      double tempArray[10][10]; 
     } 

     void setup(double x); 
     void getValues(int n); 
} 

MAIN.CPPあなたはtempArrayは、他のソースファイルでnameableにしたくない場合は

#include "FunctionWrapper.h" 

int main(){ 
    FunctionWrapper::tempArray[0][0] = 5; //Works 
} 
+0

"名前のない名前空間を使用する場合でも、私の関数で使用される配列は可視であり、関数の名前空間の外側から変更することができます。これは真実ではありません。同じ名前を持つ_different_配列は、プログラムのすべての翻訳単位で表示されますが、関数が使用する配列は、関数を含む翻訳単位でのみ変更可能です。ヘッダーファイルの名前空間は(ほとんど?)決して役に立たない。 –

答えて

6

、ドンヘッダーファイルに宣言しません。代わりに、名前のない名前空間でFunctionWrapper.cppに宣言します。次に、そのソースファイル内から直接使用することができます。

一般に、ヘッダーファイルは名前のない名前空間を使用するべきではありません。なぜなら、1つの定義ルール違反を引き起こす可能性があります。あなたの問題へのよりよい解決策は、実際には、この機能を提供するクラスを作成するかもしれないと

注:

class ValueGetter 
{ 
public: 
    ValueGetter(double x); 
    void GetValues(int n); 

private: 
    double cache[10][10]; 
}; 

この方法は、あなたがこのタイプのインスタンスを作成し、すべてのことができます状態はそのインスタンスによって所有されています。保守性とテスト容易性の向上など、グローバルな状態を回避することには多くの利点があります。

1

これはクラスとして意味があり、そのクラスのメンバーとして機能します。これらの関数はそのデータに作用し、他の誰かがそのデータにアクセスすることを望まないので、クラスにとって完璧な使い方のように思えます。なぜあなたはそれに反対していますか?ジェームズさんにさらに

1

答え(通常、優れていると)、私は物事を構築したい。このような何か:

namespace { 
class value_cache { 
    double temp_array[10][10]; 
    int x; 
    void setup(double x); 
    void internal_getValues(int); // same as your current GetValues 
public: 
    void getValues(int n) { 
     if (x != n) 
      setup(x=n);    
     internal_getValues(n); 
    } 
}; 
} 

double function(int x, int y) { 
    static value_cache c; 

    c.getValues(x); 
    // probably more stuff here. 
} 
0

私はここに3つのオプションを参照してください。

  1. .cppで匿名の名前空間を置きますあなたのメモした機能が実装されているファイル。それから、どこからでもアクセスすることはできません。
  2. メモ内の結果を含む配列をクラス内にstatic変数にします。
  3. operator()を実装するクラスを作成し、そのインスタンスを「関数」として使用します。 memoization配列は、そのクラスのプライベートメンバ変数にすることができます。

オプション1は非常にシンプルであり、動作します。もちろん、あなたの関数がマルチスレッド環境で使用されている場合は、メモ型の値のデータ構造へのアクセスのスレッド間同期について考える必要があります。

オプション2は、オプション1の変形です。個人的には、あなたがやるべきことだと思います。それはまったく同じ欠点を持っています。

オプション3は、IMHOですが、むしろ面倒です。あなたの関数のように見え、動作するようにするには、クラスのグローバル変数を宣言する必要があります。しかし、それは基本的にシングルトンです。この場合でも問題はないかもしれませんが、最終的には大きな苦痛に終わることがあります。

もう1つのオプションがありますが、それは膨大な作業です。それは基本的にはメモのテンプレートを作っています。それはオプション3のように動作しますが、ハッシュマップのキーであるという基準を満たす引数を持つ関数に対してインスタンス化できます。