繁体   English   中英

动态分配数组的静态指针

[英]Static Pointer to Dynamically allocated array

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

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

谢谢

静态成员永远不会在堆栈上分配。 当你声明它们时(当然,你明确地做了),它们被分配了空间(数据段?)。

如果查找表是类的成员是有意义的,那么让它们成为静态成员!

当一个类在堆栈上实例化时,静态成员变量不构成堆栈成本的一部分。

例如,如果您想要:

class MyClass {
    ...
    static int LookUpTable[LARGENUM];
};

int MyClass:LookUpTable[LARGENUM];

当您在堆栈上实例MyClass时,MyClass:LookUpTable指向您在上面的代码示例的最后一行显式分配的对象。 最重要的是,没有必要解除分配,因为它本质上是一个全局变量; 它不会泄漏,因为它不在堆上。

如果你根本没有释放表的内存,那么当你的程序退出时,操作系统会自动丢弃你的应用程序分配的所有内存。 这是处理仅由应用程序分配一次的内存的适当策略。

单独保留内存实际上也可以提高性能,因为您不会浪费时间在关闭时尝试显式释放所有内容,因此可能强制页面进入您分配的所有内存。 退出时,让操作系统执行此操作。

如果这些是查找 ,最简单的解决方案就是使用std :: vector:

class SomeClass {
  /* ... */
  static std::vector<element_type> static_data;
};

要初始化,您可以执行以下操作:

static_data.resize(numberOfElements);
// now initialize the contents

有了这个,你仍然可以进行类似数组的访问,如:

SomeClass::static_data[42].foo();

对于任何体面的编译器,这应该与指向本机数组的指针一样快。

为什么不创建管理查找表的单例类? 因为它们似乎需要被许多类访问; 使单例可以在全局范围内访问查找表的管理器。 然后所有类都可以使用单例getter / setter来操作查找表。 这种方法有3个优点: -

  • 如果查找表的静态容器大小变大,那么默认的堆栈大小(Windows上为1MB)会导致应用程序statrt-up本身的堆栈溢出。 使用动态分配的容器。

  • 如果您计划通过多线程访问该表,则可以扩展单例类以配合锁定访问。

  • 您还可以在应用程序退出期间在单例的dtor中进行清理。

根据想要完成的工作,我可以想到几种方法来解决这个问题。

如果数据是静态的并且是固定的,那么使用全局的静态数组并在代码中初始化将是一种很好的方法。 一切都包含在代码中,并在程序启动时加载,因此可用。 然后,所有需要访问的类都可以访问该信息。

如果数据不是静态的并且需要读入,则静态STL结构(例如矢量,列表或映射)会很好,因为它可以在向列表中添加元素时增长。 其中一些类也提供了查找方法。 根据您正在查找的数据,您可能必须提供一个结构和一些运算符,以使STL结构正常工作。

在这两种情况中的任何一种情况下,您可能想要创建一个静态全局类来读取和包含数据。 它可以负责管理初始化和访问数据。 您可以使用私有成员来指示该类是否已被读入并可供使用。 如果没有,如果有足够的信息,该类可以自己进行初始化。 另一个类可以调用静态全局类的静态函数来访问数据。 这提供了数据的封装,然后它可以被几个不同的类使用,而这些类不需要包含大型查找表。

有几种可能的优点和缺点。 我不知道该表包含什么,所以我将其称为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>执行任何操作,但主要优点是可以更轻松地动态调整大小。 这可能不是你重视的东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM