2012-01-08 74 views
2

我有一个函数,旨在执行递归计算。如果我的函数是递归编程的,则计算时间太长。因此,我通过将中间结果存储在数组中来执行记忆。隐藏变量名称空间C++

我的程序的执行过程中,我可能会调用与参数(10,0)(5,5)(2,4)等功能。因此我有一个setup(double x)功能填充用正确的价值观,整个阵列。然后我可以访问任何数组值,而无需进一步计算。我只等到x更改再次拨打setup()

我想知道如何能够在C++中实现这一点。使用一个类对我来说没有意义,因为我永远不需要创建关联的对象。我在名称空间中实现了很好的功能,但是我仍然遇到问题。即使我使用未命名的命名空间,我的函数使用的数组也是可见的,并且可以从函数的命名空间外部进行修改。如果我包含名称空间的头文件,那就是。

我的代码:

FunctionWrapper.h

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

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

Main.cpp的

#include "FunctionWrapper.h" 

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

“即使我使用了一个未命名的命名空间,我的函数使用的数组也是可见的,并且可以从该函数的命名空间之外进行修改。”这是不正确的。在您的程序的每个翻译单元中都可以看到具有相同名称的_different_数组,但函数使用的数组只能在包含您的函数的翻译单元中修改。头文件中的未命名名称空间(几乎?)永远不会有用。 – 2012-01-08 22:12:50

回答

6

如果你不想tempArray是在其他源文件可命名,唐不要在头文件中声明它。相反,将其声明在FunctionWrapper.cpp中的未命名名称空间中。然后,它只能在该源文件中直接使用。

通常,头文件不应该使用未命名的名称空间,因为它可以(并且通常会)导致违反一个定义规则。

需要注意的是一个更好的解决您的问题可能,其实是创建一个类,提供此功能:

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

我看到三个选项的位置:

  1. 把匿名命名空间中.cpp文件在哪里你的memoized函数被实现。它将无法从其他地方访问。
  2. 使该类中包含memoized结果的数组变为static变量。
  3. 创建一个实现了operator()的类,并使用它的一个实例作为“函数”。然后,memoization数组可以是该类的私有成员变量。

选项1是非常简单的,它会工作。当然,如果你的函数在多线程环境中被使用过,你将不得不考虑对memoized值数据结构进行访问的线程间同步。

选项2是选项1的变体。就我个人而言,我认为这是你应该去的。它有完全相同的缺点,但。

选项3是,恕我直言,相当费力。为了让外观和行为像你的函数一样,你必须声明这个类的全局变量。但这基本上是一个单身人士。虽然在这种情况下这可能是确定的,但它可能最终会成为一个巨大的痛苦。

还有一个选择,但它是一个大量的工作。它基本上是制作一个记忆模板。它将像选项3一样运行,但是您可以为任何参数满足作为hashmap键的标准的函数实例化它。