C++ с помощью scoped_ptr как членская переменная

Намного проще

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>

33
задан Ray Hidayat 3 February 2010 в 21:53
поделиться

7 ответов

Это - хорошая идея. Это помогает упростить Ваш код и гарантировать, что при изменении Находящегося в собственности объекта в течение времени жизни объекта предыдущий уничтожается правильно.

необходимо помнить, что 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 быть правильно уничтоженным.

29
ответ дан SCFrench 27 November 2019 в 17:40
поделиться

scoped_ptr очень хорош с этой целью. Но нужно понять его семантику. Можно сгруппировать интеллектуальные указатели с помощью двух главных свойств:

  • Copyable: интеллектуальный указатель может быть скопирован: копия и исходное владение акциями.
  • Подвижный: интеллектуальный указатель может быть перемещен: результат перемещения будет иметь владение, оригинал не будет больше владеть.

Это - довольно общая терминология. Для интеллектуальных указателей существует определенная терминология который лучшие метки те свойства:

  • Передача права собственности: интеллектуальный указатель Подвижен
  • Доля Владения: интеллектуальный указатель copyable. Если интеллектуальный указатель уже copyable, легко поддерживать семантическую передачу права собственности: Это затем - просто атомарное копия & сброс-исходного операция, ограничивая это интеллектуальными указателями определенных видов (например, только временными интеллектуальными указателями).

Позволяют нам сгруппировать доступные интеллектуальные указатели, с помощью (C)opyable, и (M)ovable, (N)either:

  1. boost::scoped_ptr: N
  2. std::auto_ptr: M
  3. boost::shared_ptr: C

auto_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, наблюдайте, что Вы у любого есть одна из этих двух удовлетворенных точек:

  • Запись деструктор (даже если это пусто) в .cpp файле Вашего класса, или
  • Делают 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.

40
ответ дан Johannes Schaub - litb 27 November 2019 в 17:40
поделиться

Это не излишество вообще, это - хорошая идея.

Это действительно требует, чтобы Ваши клиенты класса знали о повышении, все же. Это может или не может быть проблемой. Для мобильности Вы могли рассмотреть станд.:: auto_ptr, который делает (в этом случае) то же задание. Поскольку это является частным, Вы не должны волноваться о других людях, пытающихся скопировать его.

8
ответ дан CB Bailey 27 November 2019 в 17:40
поделиться

Используя 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.

5
ответ дан Martin York 27 November 2019 в 17:40
поделиться

Ограниченные по объему указатели хороши для точно этого, потому что они удостоверяются, что объекты удалены без Вас имеющий необходимость волноваться об этом как программист. Я думаю, что это - хорошее использование ограниченного по объему ptr.

я нахожу, что хорошая стратегия проектирования в целом должна постараться не освобождать память вручную как можно больше и позволить Вашим инструментам (в этом случае интеллектуальные указатели), делают это для Вас. Ручное удаление плохо по одной главной причине, поскольку я вижу его, и это - то, что код становится трудным поддержать очень быстро. Логика для выделения и освобождения памяти является часто отдельной в коде, и это приводит к дополнительным строкам, не сохраняемым вместе.

4
ответ дан Daniel Nadasi 27 November 2019 в 17:40
поделиться

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

4
ответ дан Motti 27 November 2019 в 17:40
поделиться

Почему излишество? повышение:: scoped_ptr очень легко оптимизировать, и я держал пари, что получающийся машинный код совпадет с при ручном удалении указателя в деструкторе.

scoped_ptr хорош - просто используют его :)

3
ответ дан Nemanja Trifunovic 27 November 2019 в 17:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: