Статический указатель на динамически размещаемый массив - PullRequest
2 голосов
/ 05 августа 2009

Таким образом, вопрос относительно прямой, у меня есть несколько полувысоких таблиц поиска ~ 500kb за штуку. Теперь эти одни и те же таблицы используются несколькими экземплярами классов (возможно, партиями), поэтому я не хочу хранить одни и те же таблицы в каждом классе. Поэтому я могу либо выгружать целые таблицы в стек как «статические» члены, либо иметь «статические» указатели на эти таблицы. В любом случае конструктор для класса проверит, инициализированы ли они, и сделает это, если нет. Однако мой вопрос заключается в том, что если я выберу статические указатели на таблицы (чтобы не злоупотреблять пространством стека), каким будет хороший метод для их надлежащей очистки.

Также обратите внимание, что я рассмотрел использование boost :: share_ptr, но решил не делать этого, это очень маленький проект, и я не собираюсь добавлять какие-либо зависимости.

Спасибо

Ответы [ 6 ]

4 голосов
/ 05 августа 2009

Статические члены никогда не будут размещаться в стеке. Когда вы объявляете их (что, конечно, вы делаете явно), им где-то назначается пространство (сегмент данных?).

Если имеет смысл, что таблицы поиска являются членами класса, тогда сделайте их статическими членами!

Когда в стеке создается экземпляр класса, статические переменные-члены не составляют часть стоимости стека.

Если, например, вы хотите:

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

int MyClass:LookUpTable[LARGENUM];

Когда вы создаете экземпляр MyClass в стеке, MyClass: LookUpTable указывает на объект, который вы явно разместили в последней строке примера кода выше. Лучше всего, что нет необходимости освобождать его, так как это по сути глобальная переменная; он не может просочиться, так как его нет в куче.

2 голосов
/ 05 августа 2009

Если вы вообще не освобождаете память для таблиц, то при выходе из вашей программы ОС автоматически выбрасывает всю память, выделенную вашим приложением. Это подходящая стратегия для обработки памяти, которая выделяется вашим приложением только один раз.

Оставляя только память, можно на самом деле улучшить производительность тоже, потому что вы не будете тратить время на выключение, пытаясь явно освободить все и, следовательно, возможно, заставить страницу загружаться для всей выделенной памяти. Просто дайте ОС сделать это при выходе.

1 голос
/ 05 августа 2009

Почему бы вам не создать одноэлементный класс, который управляет таблицами поиска? Как кажется, к ним должен получить доступ ряд классов; сделайте синглтон менеджером таблиц поиска, доступных в глобальном масштабе. Тогда все классы могут использовать одноэлементные методы получения / установки для управления таблицами поиска. У этого подхода есть 3 преимущества: -

  • Если статический размер контейнера для таблицы поиска становятся большими, тогда размер стека по умолчанию может (1 МБ на Windows) приводит к переполнению стека Само приложение. Используйте контейнер, который выделяется динамически.

  • Если вы планируете получить доступ к таблице через несколько потоков, класс синглтона может быть расширен, чтобы сопровождать заблокированный доступ.

  • Вы также можете выполнить очистку в dtor синглтона при выходе из приложения.

1 голос
/ 05 августа 2009

Если это поиск таблиц , самое простое решение - просто использовать std :: vector:

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

Для инициализации вы можете выполнить:

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

С этим вы все еще можете делать доступ к массиву, как в:

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

И с любым приличным компилятором это должно быть так же быстро, как указатель на собственный массив.

0 голосов
/ 05 августа 2009

Есть несколько возможностей с различными преимуществами и недостатками. Я не знаю, что содержит таблица, поэтому назову ее 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>, если хотите, но главное преимущество в том, что его можно легче изменить динамически. Это может быть не то, что вы цените.

0 голосов
/ 05 августа 2009

Я могу придумать несколько способов приблизиться к этому в зависимости от того, что пытается быть достигнуто.

Если данные статичны и фиксированы, хорошим подходом будет использование статического массива, который является глобальным и инициализируется в коде. Все содержится в коде и загружается при запуске программы, чтобы она была доступна. Тогда весь класс, которому нужен доступ, может получить доступ к информации.

Если данные не являются статичными и должны считываться, статическая структура STL, такая как вектор, список или карта, подойдет, поскольку она может расти по мере добавления элементов в список. Некоторые из этих классов также предоставляют методы поиска. В зависимости от данных, которые вы ищете, вам может потребоваться предоставить структуру и некоторый оператор, чтобы структуры STL работали правильно.

В любом из двух случаев вы можете создать статический глобальный класс для чтения и хранения данных. Он может позаботиться об управлении инициализацией и доступом к данным. Вы можете использовать закрытые члены, чтобы указать, был ли класс прочитан и доступен ли для использования. Если нет, класс может выполнить инициализацию самостоятельно, если у него достаточно информации. Другой класс может вызывать статическую функцию статического глобального класса для доступа к данным. Это обеспечивает инкапсуляцию данных, и затем они могут использоваться несколькими различными классами, при этом этим классам не нужно работать с большой таблицей поиска.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...