Вот оптимизированная реализация:
public static final Comparator & lt; CharSequence & gt; VERSION_ORDER = new Comparator & lt; CharSequence & gt; () {@Override public int compare (CharSequence lhs, CharSequence rhs) {int ll = lhs.length (), rl = rhs.length (), lv = 0, rv = 0, li = 0, ri = 0; char c; do {lv = rv = 0; while (-ll & gt; = 0) {c = lhs.charAt (li ++); если (c & lt; '0' || c & gt; '9') break; lv = lv * 10 + c - '0'; } while (-rl & gt; = 0) {c = rhs.charAt (ri ++); если (c & lt; '0' || c & gt; '9') break; rv = rv * 10 + c - '0'; }} while (lv == rv & amp; & amp; (ll & gt; = 0 || rl & gt; = 0)); return lv - rv; }};
Результат:
"0.1" - "1.0" = -1 "1.0" - "1.0" = 0 "1.0" - "1.0.0 "= 0" 10 "-" 1.0 "= 9" 3.7.6 "-" 3.7.11 "= -5" foobar "-" 1.0 "= -1
delete
неявно вызывает деструктор, вам не нужно (точнее: не должно) называть его напрямую.
Деструктор никогда не освободит память, занятую объектом (она может находиться в стеке, а не в куче, и объект не знает, но деструктор удалит любую память, выделенную компонентами объекта.
Чтобы освободить память объекта выделенного в куче, вы должны называть delete
.
Когда вы пишете свой собственный класс, C ++ предоставит деструктор по умолчанию , чтобы освободить память, выделенную объектами компонента (например, a QString
, который является членом вашего класса), но если вы явно выделяете память (или другие ресурсы) в своем конструкторе, обязательно укажите деструктор, который будет явно освобождать эти ресурсы.
Другое общее правило относительно ваших собственных классов: если вы отмечаете какие-либо методы virtual
, ваш деструктор должен быть virtual
, а также (даже если вы полагаетесь на деструктор по умолчанию), так что правильный деструктор вызывается для любых классов, полученных из ваших.
delete является предпочтительным. Просто вызов деструктора не освобождает память, выделенную новым.
Обычно вы никогда не хотите явно вызвать деструктор. Просто используйте delete
.
Я не предпочитаю никого.
Явный вызов деструктора очень нужен очень редко, только когда вы отделяете выделение памяти от времени жизни объекта. Возможно, это понадобится при реализации пользовательского класса контейнера.
Явным delete
является, возможно, законным способом уничтожения объекта, динамически созданного с помощью выражения new
, но в большинстве приложений он не должен быть ненужным код, поскольку он сигнализирует место, где могут возникать потенциальные несоответствия между новым и удаленным, и областями с потенциальными проблемами безопасности исключений.
Если время жизни объекта ограничено блоком, то локальная переменная обычно должна быть предпочтительной в качестве распределения памяти служебные данные, как правило, ниже, и объект будет автоматически очищен правильно, однако блок будет удален.
{
// ...
Object object( ... );
} // object destructor run, however this block is exited.
Если есть какая-то причина, что это не может быть необходимо (например, у объекта есть чрезмерный статический размер ) или его продолжительность жизни не может быть сопоставлена с определенной областью, тогда обычно для управления временем жизни объектов должен использоваться какой-то умный указатель. Самый простой интеллектуальный указатель, который доступен в стандартном C ++, - std::auto_ptr
, который может использоваться для объектов с динамическим распределением блоков, но имеет «удивительное» поведение при копировании и присваивании. Что-то вроде tr1::shared_ptr
(или boost::shared_ptr
) являются общими альтернативами, в которых требуется совместное владение.
{
std::auto_ptr<Object> object(new Object(...));
// ...
} // *object destructor run, however this block is exited.
Вызов delete вызовет деструктор, а затем освободит память.
Вызвать деструктор явно вызовет только деструктор, а не освободит память.
Поэтому вы должны почти всегда вызов delete: за исключением случаев, когда вы хотите вызвать деструктор без освобождения памяти, например потому что вы построили объект с помощью размещения new .
Используйте delete
. Он вызывает объекты destructor , а затем освобождает выделенную память.
Кроме того, это не деконструктор, а деструктор.
Вы никогда не должны называть деструктора самостоятельно. delete вызовет его для вас
operator delete
, но это не уничтожает объекты, оно вызывается, когда оно соответствует operator new
в новом выражении, и конструкция объекта завершается сбоем после того, как распределение памяти успешно отменяет выделенную необработанную память. Если новое выражение места размещения успешно завершено, то правильным способом уничтожения объекта является явный вызов деструктора, за которым следует соответствующее освобождение (если применимо).
– CB Bailey
3 June 2010 в 22:20
Что-то еще, чтобы рассмотреть:
, поскольку delete
вызывает деструктор внутри себя, это ошибка для обоих, т. е. вызов деструктора, а затем удаление. Итак, следующий код:
Foo* px = new Foo;
// …
px->~Foo();
delete px;
Выдает неприятную ошибку. В зависимости от действий, предпринятых в фактическом деструкторе, это может остаться незамеченным в течение некоторого времени, поскольку компилятор фактически разрешает этот код. Это может привести к тонким, труднодоступным ошибкам.
Когда вы используете динамическое выделение памяти для создания объекта в это время, вы можете использовать оператор delete для уничтожения / удаления объекта, но когда вы не используете DMA в это время, пытаетесь удалить объект, используя команду delete, вызывается ошибка. Один из способов справиться с этой ситуацией - написать свой собственный деструктор в явном виде и вызвать деструктор, используя объект для его уничтожения.