Зачем увеличивать указатели с областью видимости

Какова цель указателя с ограниченным объемом? Насколько я понимаю, указатель с областью действия управляет памятью в блоке кода. Если я хочу объявить переменную в блоке, я могу просто объявить ее в стеке и не беспокоиться об очистке.


person Jimm    schedule 24.05.2012    source источник
comment
boost.org/doc/libs/1_36_0/ libs / smart_ptr / scoped_ptr.htm # Handle /   -  person R. Martinho Fernandes    schedule 24.05.2012


Ответы (4)


Нет, если он динамического размера или типа. Кроме того, указатели с ограниченной областью видимости можно менять местами, а в C ++ 11 unique_ptr можно перемещать, поэтому их область действия не ограничена строго.

person Puppy    schedule 24.05.2012
comment
За исключением того, что основная причина использовать scoped_ptr, а не auto_ptr, состоит в том, чтобы дать читателям вашего кода знать, что вы намерены использовать инициализацию получения ресурсов только для текущей области и не имеете намерения передавать право собственности ... похоже, что swap не предполагаемое использование. - person Ben Voigt; 24.05.2012
comment
@BenVoigt: Но он есть, и его можно использовать. - person Puppy; 24.05.2012
comment
Вот старая ветка, в которой обсуждается, почему swap стал требованием (в основном поэтому scoped_ptr можно использовать как член копируемого класса). - person Jesse Good; 24.05.2012
comment
Что вы имеете в виду под динамическим размером или типом? - person Jimm; 25.05.2012

В отличие от данных на основе стека, scoped_ptr имеет член reset () - другими словами, вы можете создавать / разрушать, сколько душе угодно. При этом вы можете использовать нулевой указатель (технически operator unspecified-bool-type) в качестве флага, указывающего, существует ли сконструированный объект в любой момент времени. Это также позволяет вам упорядочивать построение / уничтожение независимо от области действия переменной, если это необходимо.

Также учтите, что вы можете объявить scoped_ptr как член класса, а не только как переменную стека. В документах предлагается использовать scoped_ptr для реализовать идиому дескриптора / тела (чтобы скрыть детали реализации класса).

Наконец, чтобы уточнить пункт DeadMG «Нет, если он динамического типа», вы можете использовать scoped_ptr для реализации полиморфная операция:

{
scoped_ptr<Base> a( mode ? new DerivedA : new DerivedB );
a->polymorphic_function();
}

На самом деле это невозможно сделать с помощью простого распределения на основе стека.


Также см. Здесь: C ++ 0x unique_ptr заменяет scoped_ptr, переходящий во владение?

person Brent Bradburn    schedule 24.05.2012
comment
@GManNickG: Я не думаю, что boost :: variant обеспечивает хорошую замену полиморфизму через scoped_ptr - хотя и интересно. Спасибо! - person Brent Bradburn; 24.05.2012
comment
Я не понимаю, как получить доступ к производному классу через интерфейс базового класса. Может я что-то упускаю. - person Brent Bradburn; 24.05.2012
comment
Понятно: boost::variant<DerivedA,DerivedB> v = DerivedB(); Base & r = boost::get<DerivedB>(v); r.polymorphic_function(); Круто. - person Brent Bradburn; 24.05.2012

Дело в том, что вы можете создавать и очищать указатель в определенной лексической области. Это может быть полезно в различных ситуациях и гарантирует отсутствие утечек памяти, если забыть delete, если вы использовали new явно, что не рекомендуется.

Вы должны помнить, что boost::scoped_ptr не копируемый, поэтому полностью владеет своим ресурсом в течение всего срока его существования. Это также делает его более безопасным, чем boost::shared_ptr, поскольку позволяет избежать копирования ресурса или случайного совместного использования.

{ //Some Scope

  boost::scoped_ptr<int> i_ptr;
  // do something with pointer

} // leave scope, pointer is cleaned up
person Tony The Lion    schedule 24.05.2012

обычно стеки потоков имеют ограничения памяти (см. размер стека потоков).

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

void foo(Object*obj)
{
    //this will ensure that object gets cleaned up even if doFoo() throws an exception
    boost::scoped_ptr<Object> objCleaner(obj);
    obj->doFoo();
}
person mohaps    schedule 24.05.2012
comment
Я могу объявить указатель в стеке, и он будет автоматически очищен, когда функция выйдет из области видимости, либо успешно, либо через исключение. Правильный? - person Jimm; 25.05.2012
comment
{X * x =} это не приведет к удалению указателя x, когда он выходит за пределы области видимости. someObj будет удален, когда он выйдет за пределы области видимости. {X * y = new X ();} для этого типа кода потребуется ptr с областью видимости для автоматической очистки - person mohaps; 30.05.2012