动态分配数组的静态指针

时间:2009-08-05 02:38:11

标签: c++ windows

所以问题相对简单,我有几个半大的查找表~500kb一块。现在这些完全相同的表被几个类实例化(可能很多)使用,考虑到这一点,我不想在每个类中存储相同的表。所以我可以将整个表作为“静态”成员转储到堆栈中,或者我可以对这些表有“静态”指针。在任何一种情况下,类的构造函数都将检查它们是否已初始化,如果不是,则执行此操作。但是,我的问题是,如果我选择表的静态指针(以免滥用堆栈空间),那么适当清理它们的好方法是什么。

另请注意,我考虑过使用boost :: share_ptr,但选择不这样做,这是一个非常小的项目,我不打算添加任何依赖项。

谢谢

6 个答案:

答案 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>执行其中任何操作,但主要优点是可以更轻松地动态调整大小。这可能不是你重视的东西。