所以问题相对简单,我有几个半大的查找表~500kb一块。现在这些完全相同的表被几个类实例化(可能很多)使用,考虑到这一点,我不想在每个类中存储相同的表。所以我可以将整个表作为“静态”成员转储到堆栈中,或者我可以对这些表有“静态”指针。在任何一种情况下,类的构造函数都将检查它们是否已初始化,如果不是,则执行此操作。但是,我的问题是,如果我选择表的静态指针(以免滥用堆栈空间),那么适当清理它们的好方法是什么。
另请注意,我考虑过使用boost :: share_ptr,但选择不这样做,这是一个非常小的项目,我不打算添加任何依赖项。
谢谢
答案 0 :(得分:4)
永远不会在堆栈上分配静态成员。当你声明它们时(当然,你明确地做了),它们被分配了空间(数据段?)。
如果查找表是类的成员是有意义的,那么让它们成为静态成员!
当一个类在堆栈上实例化时,静态成员变量不构成堆栈成本的一部分。
例如,如果你想要:
class MyClass {
...
static int LookUpTable[LARGENUM];
};
int MyClass:LookUpTable[LARGENUM];
当您在堆栈上实例MyClass时,MyClass:LookUpTable指向您在上面的代码示例的最后一行显式分配的对象。最重要的是,没有必要解除分配,因为它本质上是一个全局变量;它不会泄漏,因为它不在堆上。
答案 1 :(得分:2)
如果您根本没有释放表的内存,那么当您的程序退出时,操作系统将自动丢弃您的应用程序分配的所有内存。这是处理仅由应用程序分配一次的内存的适当策略。
单独保留内存实际上也可以提高性能,因为您不会浪费时间在关闭时尝试显式释放所有内容,因此可能强制页面进入您分配的所有内存。退出时,让操作系统执行此操作。
答案 2 :(得分:1)
如果这些是查找表,最简单的解决方案就是使用std :: vector:
class SomeClass {
/* ... */
static std::vector<element_type> static_data;
};
要进行初始化,您可以执行以下操作:
static_data.resize(numberOfElements);
// now initialize the contents
有了这个,你仍然可以进行类似数组的访问,如:
SomeClass::static_data[42].foo();
对于任何体面的编译器,这应该与指向本机数组的指针一样快。
答案 3 :(得分:1)
为什么不创建管理查找表的单例类?因为它们似乎需要被许多类访问;使单例可以在全局范围内访问查找表的管理器。然后所有类都可以使用单例getter / setter来操作查找表。这种方法有3个优点: -
如果静态容器的大小为 查找表变大了 默认堆栈大小可能(1MB开启 Windows)导致堆栈溢出 申请认证本身。使用动态分配的容器。
如果您打算通过多线程访问该表,可以扩展单例类以锁定访问权限。
您还可以在申请退出期间在单身人士的清单中进行清理。
答案 4 :(得分:0)
根据想要完成的事情,我可以想出几种方法来解决这个问题。
如果数据是静态的并且是固定的,那么使用全局的静态数组并在代码中初始化将是一种很好的方法。一切都包含在代码中,并在程序启动时加载,因此可用。然后,所有需要访问的类都可以访问该信息。
如果数据不是静态的并且需要读入,则静态STL结构(例如矢量,列表或映射)会很好,因为它可以在向列表中添加元素时增长。其中一些类也提供了查找方法。根据您正在查找的数据,您可能必须提供一个结构和一些运算符,以使STL结构正常工作。
在这两种情况中的任何一种情况下,您可能想要创建一个静态全局类来读取和包含数据。它可以负责管理初始化和访问数据。您可以使用私有成员来指示该类是否已被读入并可供使用。如果没有,如果有足够的信息,该类可以自己进行初始化。另一个类可以调用静态全局类的静态函数来访问数据。这提供了数据的封装,然后它可以被几个不同的类使用,而这些类不需要包含大型查找表。
答案 5 :(得分:0)
有几种可能的优点和缺点。我不知道该表包含什么,因此我将其称为Entry
。
如果你只想在程序退出时确保内存消失,请使用全局auto_ptr:
auto_ptr<Entry> pTable;
您可以随时初始化它,并在程序退出时自动删除它。不幸的是,它会污染全局命名空间。
听起来您在同一类的多个实例中使用相同的表。在这种情况下,通常将它作为该类的静态指针:
class MyClass {
...
protected:
static auto_ptr<Entry> pTable;
};
如果你想在不同的类的实例中访问它,那么你可能会使它成为函数的静态成员,当程序退出时它们也会被删除,但真的很好看的东西是在输入函数之前不会初始化它。即,如果从未调用该函数,则不需要分配资源:
Entry* getTable() {
static auto_ptr<Entry> pTable = new Entry[ gNumEntries ];
return pTable;
}
如果您愿意,可以使用std::vector<Entry>
而不是auto_ptr<Entry>
执行其中任何操作,但主要优点是可以更轻松地动态调整大小。这可能不是你重视的东西。