Намного проще
var timer;
function setTimer(event){
if(timer)
{
clearInterval(timer)
}
var timerValue = document.getElementById("timerstart").value ;
timer = setInterval(function(){
if(timerValue > 0){
document.getElementById("timer").innerHTML=timerValue;
timerValue --;
} else {
clearInterval(timer)
}
},1000);
}
<div>
<label>Start Timer After(seconds)</label>
<input type="text" name="timerstart" id="timerstart" />
</div>
<button onclick="setTimer(event)" >Start Timer</button>
<div ><span>Timer : </span><span id="timer"></span></div>
Это - хорошая идея. Это помогает упростить Ваш код и гарантировать, что при изменении Находящегося в собственности объекта в течение времени жизни объекта предыдущий уничтожается правильно.
необходимо помнить, что scoped_ptr noncopyable, тем не менее, который делает класс noncopyable по умолчанию, пока/если Вы не добавляете своего собственного конструктора копии, и т.д. (Конечно, использование конструктора копии по умолчанию в случае необработанных указателей было бы нет - нет также!)
, Если Ваш класс имеет больше чем одно поле указателя, то использование scoped_ptr на самом деле повышает уровень безопасности исключения в одном случае:
class C
{
Owned * o1;
Owned * o2;
public:
C() : o1(new Owned), o2(new Owned) {}
~C() { delete o1; delete o2;}
};
Теперь, предположите, что во время конструкции C второе, "новое Находящийся в собственности", выдает исключение (из памяти, например). o1 будет пропущен, потому что C:: ~C () (деструктор) не назовут, потому что объект еще не был полностью создан. Деструктор любого полностью созданного членского поля делает , названы все же. Так, использование scoped_ptr вместо простого указателя позволит o1 быть правильно уничтоженным.
scoped_ptr очень хорош с этой целью. Но нужно понять его семантику. Можно сгруппировать интеллектуальные указатели с помощью двух главных свойств:
Это - довольно общая терминология. Для интеллектуальных указателей существует определенная терминология который лучшие метки те свойства:
Позволяют нам сгруппировать доступные интеллектуальные указатели, с помощью (C)opyable
, и (M)ovable
, (N)either
:
boost::scoped_ptr
: Nstd::auto_ptr
: Mboost::shared_ptr
: Cauto_ptr
имеет одну большую проблему, в которой он осознает Подвижное понятие с помощью конструктора копии. Это вызвано тем, что, Когда auto_ptr был принят в C++, еще не было способа исходно поддерживать семантику перемещения с помощью конструктора перемещения, в противоположность новому Стандарту C++. Таким образом, можно сделать следующее с auto_ptr, и это работает:
auto_ptr<int> a(new int), b;
// oops, after this, a is reset. But a copy was desired!
// it does the copy&reset-of-original, but it's not restricted to only temporary
// auto_ptrs (so, not to ones that are returned from functions, for example).
b = a;
Так или иначе, как мы видим в Вашем случае, Вы не сможете передать владение другому объекту: Ваш объект в действительности будет non-copyable. И в следующем Стандарте C++, это будет неподвижно, если Вы останетесь с scoped_ptr.
Для реализации Вашего класса с scoped_ptr, наблюдайте, что Вы у любого есть одна из этих двух удовлетворенных точек:
Owned
, полностью определяет класс. Иначе при создании объекта Примера компилятор неявно определит деструктор для Вас, которые назвали бы деструктор scoped_ptr:
~Example() { ptr.~scoped_ptr<Owned>(); }
, Который затем выполнил бы scoped_ptr вызов boost::checked_delete
, который будет жаловаться приблизительно [1 111] являющиеся неполным, в случае, если Вы не сделали ни одной из вышеупомянутых двух точек. При определении собственного dtor в .cpp файле неявный вызов к деструктору scoped_ptr был бы выполнен из .cpp файла, в который Вы могли поместить определение Вашего Owned
класс.
у Вас есть та же самая проблема с auto_ptr, но у Вас есть еще одна проблема: Предоставление auto_ptr с неполным типом в настоящее время является неопределенным поведением (возможно, это будет зафиксировано для следующей версии C++). Так, при использовании auto_ptr Вы имеете для создания Принадлежавшим полный тип в заголовочном файле.
shared_ptr не имеет той проблемы, потому что это использует полиморфное средство удаления, которое выполняет непрямой вызов к удалению. Таким образом, функция удаления не инстанцируют в то время, когда деструктор инстанцируют, но в то время, когда средство удаления создается в конструкторе shared_ptr.
Это не излишество вообще, это - хорошая идея.
Это действительно требует, чтобы Ваши клиенты класса знали о повышении, все же. Это может или не может быть проблемой. Для мобильности Вы могли рассмотреть станд.:: auto_ptr, который делает (в этом случае) то же задание. Поскольку это является частным, Вы не должны волноваться о других людях, пытающихся скопировать его.
Используя scoped_ptr хорошая идея.
Хранение и вручную уничтожение указателя не так просты, как Вы думаете. Особенно, если существует больше чем один НЕОБРАБОТАННЫЙ указатель в Вашем коде. Если безопасность исключения и не просачивающаяся память является приоритетом затем, Вам нужно много дополнительного кода для получения его корректный.
Для запуска необходимо удостовериться, что Вы правильно определяете все четыре метода по умолчанию. Это вызвано тем, что сгенерированная версия компилятора этих методов хорошо для обычных объектов (включая интеллектуальные указатели), но в нормальном случае приведет к проблемам с обработкой указателя (Ищите Мелкую проблему Копии).
при использовании scoped_ptr затем, Вы не должны волноваться ни об одном из тех.
Теперь, если у Вас есть больше чем один НЕОБРАБОТАННЫЙ указатель в Вашем классе (или другие части Вашего конструктора может бросить). Необходимо ЯВНО иметь дело за исключениями во время конструкции и разрушением.
class MyClass
{
public:
MyClass();
MyClass(MyClass const& copy);
MyClass& operator=(MyClass const& copy);
~MyClass();
private
Data* d1;
Data* d2;
};
MyClass::MyClass()
:d1(NULL),d2(NULL)
{
// This is the most trivial case I can think off
// But even it looks ugly. Remember the destructor is NOT called
// unless the constructor completes (without exceptions) but if an
// exception is thrown then all fully constructed object will be
// destroyed via there destructor. But pointers don't have destructors.
try
{
d1 = new Data;
d2 = new Data;
}
catch(...)
{
delete d1;
delete d2;
throw;
}
}
Взгляд, насколько легче scopted_ptr.
Ограниченные по объему указатели хороши для точно этого, потому что они удостоверяются, что объекты удалены без Вас имеющий необходимость волноваться об этом как программист. Я думаю, что это - хорошее использование ограниченного по объему ptr.
я нахожу, что хорошая стратегия проектирования в целом должна постараться не освобождать память вручную как можно больше и позволить Вашим инструментам (в этом случае интеллектуальные указатели), делают это для Вас. Ручное удаление плохо по одной главной причине, поскольку я вижу его, и это - то, что код становится трудным поддержать очень быстро. Логика для выделения и освобождения памяти является часто отдельной в коде, и это приводит к дополнительным строкам, не сохраняемым вместе.
Я не думаю, что это - излишество, это документирует семантику участника намного лучше, чем наличие необработанного указателя и менее подвержено ошибкам.
Почему излишество? повышение:: scoped_ptr очень легко оптимизировать, и я держал пари, что получающийся машинный код совпадет с при ручном удалении указателя в деструкторе.
scoped_ptr хорош - просто используют его :)