Единственный безопасный способ гарантировать, что StringBuilder
подходит для сборки мусора, такой же, как и все объекты: уничтожить все ссылки на него. Это означает, что нужно явно установить его на null
или позволить ему выпасть из области видимости.
Кроме того, вы не можете контролировать, когда освобождается память. Максимум, что вы можете сделать, это запросить сборку мусора, и это редко хорошая идея (не говоря уже о том, что вы просто запрашиваете, а не заказываете JVM для сбора мусора).
Другие предложенные вами варианты не гарантируют освобождение всей памяти, если вы не углубились в код и не уверены, что полностью очищаете состояние объекта. Вот почему обычно намного лучше просто обнулить всю ссылку на объект и начать все сначала, если вы хотите убедиться, что все «чисто».
Просто объявите cs
как:
mutable CRITICAL_SECTION cs;
или иначе удалите пункт константы на size()
Ввод критического раздела изменяет CRITICAL_SECTION
, и отъезд изменяет его снова. Начиная с ввода и отъезда критического раздела не делает size()
вызов метода логически не -const
, Я сказал бы, что отпуск это объявило const
, и сделайте cs
mutable
. Это - тип ситуации mutable
был представлен для.
Также - смотрят на предложения Martin York и Joe Mucchiello - используют RAII, когда это возможно, для контакта с любым видом ресурсов, которые должны быть очищены. Это работает точно также на критические разделы, как это делает для указателей и дескрипторов файлов.
Также кодом выше не является безопасное Исключение.
Нет никакой гарантии, что push_back () pop_back () не бросит. Если они сделают то они оставят Ваш критический раздел постоянно заблокированным. Необходимо создать класс блокировщика, который называет EnterCriticalSection () на конструкции и LeaveCriticalSection () на разрушении.
Также это делает Ваши методы намного легче читать. (см. ниже),
class CriticalSectionLock
{
public:
CriticalSectionLock(CRITICAL_SECTION& cs)
: criticalSection(cs)
{
EnterCriticalSection(&criticalSection);
}
~CriticalSectionLock()
{
LeaveCriticalSection(&criticalSection);
}
private:
CRITICAL_SECTION& criticalSection;
};
// Usage
template
unsigned int SharedVector::size() const
{
CriticalSectionLock lock(cs);
return vect.size();
}
Другая вещь необходимо волноваться о. Удостоверяется, что при уничтожении объекта, у Вас есть владение и что никто больше не пытается взять владение во время разрушения. Надо надеяться, Ваш DestoryCriticalSection () заботится об этом.
EnterCriticalSection
не берет аргумент константы. Это - ошибка компиляции, BTW, не связывающаяся ошибка...
Кроме того, Вы уверенный, что Вы хотите передать в критическом разделе в Ваш ctor, и затем иметь ctor работают InitializeCriticalSection
звонить? Если бы Вы хотите совместно использовать свой критический раздел, я предполагаю, что Вы инициализировали бы его сначала и затем раздали бы его.
Я предпочитаю использовать отдельный объект Приобретения по Вашему коду. Ваш код, если хрупкий, когда исключение происходит между вызовами Введения и Отпуска:
class CS_Acquire {
CRITICAL_SECTION &cs;
public:
CS_Acquire(CRITICAL_SECTION& _cs) : cs(_cs) { EnterCriticalSection(cs); }
~CS_Acquire() { LeaveCriticalSection(cs); }
};
Затем в Ваших методах класса Вы кодировали бы его как:
template <typename T>
void SharedVector::PushBack(const T& value) {
CS_Acquire acquire(&cs);
vect.push_back(value);
}
таким образом это - что-то не так с правами доступа. Я сделал размер () неконстантой метода, и теперь это в порядке.
Я вижу, что Вы объявляете пустого конструктора копии:
SharedVector(const SharedVector& rhs) {}
Поскольку я уверен, что Вы знаете, эта функция ничего не делает, и она также уезжает cs
неинициализированный. Поскольку Ваш класс содержит экземпляр a CRITICAL_SECTION
, несомненно, необходимо будет запретить конструктору копии и вызовам оператора присваивания, если Вы не собираетесь реализовать их полностью. Можно сделать это путем размещения следующих объявлений в private
раздел Вашего класса:
SharedVector(const SharedVector &);
SharedVector &operator=(const SharedVector &);
Это препятствует тому, чтобы компилятор автоматически генерировал неверные версии этих методов и также препятствует тому, чтобы Вы назвали их в другом коде, который Вы пишете (потому что это только объявления, но не определения с {}
блоки кода).
Кроме того, как Arnout упомянул, конструктор, который берет a CRITICAL_SECTION&
аргумент кажется неправильным. То, что делает Ваша реализация, скопировать переданный - в критическом разделе к cs
(который не является допустимой вещью сделать с a CRITICAL_SECTION
), затем звонит InitializeCriticalSection(&cs)
который перезаписывает копию, Вы просто сделали и создаете новый критический раздел. Вызывающей стороне, которая передала в критическом разделе, это, кажется, делает неправильную вещь путем эффективного игнорирования того независимо от того, что было передано в.