2010-02-23 3 views
156

Что означает «Приобретение ресурсов» - это Инициализация (RAII)?Что означает «Приобретение ресурсов» - это инициализация (RAII)?

+11

http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization – 2010-02-23 20:39:53

+8

Это то, что заставляет его домой для меня. http://www.stroustrup.com/bs_faq2.html#finally –

+1

Ссылка Microsoft с 3 предложениями и 2 примерами пока очень ясна! https://msdn.microsoft.com/en-us/library/hh438480.aspx –

ответ

85

Это идиома программирования, который вкратце означает, что вы

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

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

Это хорошо зарекомендовавшая себя практика на C++, поскольку, помимо безопасного использования ресурсов, он делает ваш код намного чище, так как вам не нужно смешивать код обработки ошибок с основной функциональностью.

*Обновление: «local» может означать локальную переменную или нестатистическую переменную-член класса. В последнем случае переменная-член инициализируется и уничтожается с помощью объекта-владельца.

**Обновление2:, как @sbi указывал, ресурс - хотя часто выделяется внутри конструктора - также могут быть выделены снаружи и передается в качестве параметра.

+0

AFAIK, аббревиатура не означает, что объект должен находиться в локальной (стек) переменной.Он может быть переменной-членом другого объекта, поэтому, когда объект «удержания» уничтожается, объект-член также уничтожается, и ресурс освобождается. Фактически, я считаю, что аббревиатура означает только то, что для инициализации и освобождения ресурса не существует методов 'open()'/'close()', просто конструктор и деструктор, поэтому «удержание» ресурса - это всего лишь время жизни объекта, независимо от того, выполняется ли это время жизни контекстом (стеком) или явно (динамическое распределение) – Javier

+1

На самом деле ничего не говорится о том, что ресурс должен быть приобретен в конструкторе. Файловые потоки, строки других контейнеров делают это, но ресурс также может быть * передан * конструктору, как это обычно бывает с интеллектуальными указателями. Поскольку ваш ответ является наиболее распространенным, вы можете исправить это. – sbi

+0

Это не аббревиатура, это аббревиатура. Большинство людей произносят это слово «ar ey ay ay», поэтому на самом деле он не претендует на акроним, как говорят DARPA, который произносится как DARPA вместо написания. Кроме того, я бы сказал, что RAII - это парадигма, а не просто идиома. – dtech

37

«RAII» означает «Получение ресурса есть инициализация» и на самом деле очень неправильно, так как это не ресурс приобретения (и инициализация объекта) она связана с, но отпуская ресурса (с помощью уничтожения объекта).
Но RAII - это имя, которое мы получили, и оно прилипает.

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

{ 
    raii obj(acquire_resource()); 
    // ... 
} // obj's dtor will call release_resource() 

конечно, объекты не всегда местные, автоматические объекты. Они также могут быть членами класса:

class something { 
private: 
    raii obj_; // will live and die with instances of the class 
    // ... 
}; 

Если такие объекты управляют памятью, их часто называют «умными указателями».

Существует много вариантов этого. Например, в первых фрагментах кода возникает вопрос, что произойдет, если кто-то захочет скопировать obj. Самый простой выход - просто запретить копирование. std::unique_ptr<>, умный указатель, который будет частью стандартной библиотеки, как показано на следующем стандарте C++, делает это.
Другой такой умный указатель, std::shared_ptr, имеет свойство «совместного использования» ресурса (динамически выделенного объекта), которое он удерживает.То есть, он может свободно копироваться и все копии относятся к одному и тому же объекту. Умный указатель отслеживает, сколько копий относится к одному и тому же объекту, и удаляет его, когда последний уничтожается.
Третий вариант представлен std::auto_ptr, который реализует своего рода семантику перемещения: объект принадлежит только одному указателю, и попытка копирования объекта приведет (посредством синтаксического хакера) к передаче права собственности на объект на объект операция копирования.

+3

'std :: auto_ptr' - устаревшая версия' std :: unique_ptr'. 'std :: auto_ptr' - симулированная семантика движения, насколько это было возможно в C++ 98,' std :: unique_ptr' использует новую семантику перемещения C++ 11. Новый класс был создан, потому что семантика перемещения C++ 11 более явна (требуется «std :: move», кроме как из временного), в то время как для любой копии из константы в std :: auto_ptr' она была установлена ​​по умолчанию. –

8

Книга C++ Programming with Design Patterns Revealed описывает RAII как:

  1. Эквайринг все ресурсы
  2. Использование ресурсов
  3. Высвобождение ресурсов

Где

  • ресурсы являются impleme как классы, и все указатели вокруг них обертывают оболочками (делая их умными указателями).

  • Ресурсы приобретаются путем вызова их конструкторов и освобождения неявно (в обратном порядке получения) путем вызова их деструкторов.

+1

@Brandin Я отредактировал свой пост, чтобы читатели сосредоточились на содержании, которое имеет значение, вместо того, чтобы обсуждать серое пространство авторского права о том, что представляет собой справедливое использование. – Dennis

237

Это действительно страшное имя для невероятно мощной концепции и, возможно, одной из тех вещей, которые разработчики C++ теряют, когда переключаются на другие языки. Было немного движения, чтобы попытаться переименовать эту концепцию как Ограниченное областью Управление ресурсами, хотя похоже, что оно пока не появилось.

Когда мы говорим «Ресурс», мы имеем в виду не только память, но и файловые дескрипторы, сетевые сокеты, дескрипторы баз данных, объекты GDI ... Короче говоря, вещи, которые у нас есть, чтобы иметь возможность контролировать их использование. Аспект «Связанный с областью» означает, что время жизни объекта связано с областью действия переменной, поэтому, когда переменная выходит из области видимости, деструктор освободит ресурс. Очень полезным свойством этого является то, что он обеспечивает большую безопасность исключений. Например, сравните:

RawResourceHandle* handle=createNewResource(); 
handle->performInvalidOperation(); // Oops, throws exception 
... 
deleteResource(handle); // oh dear, never gets called so the resource leaks 

С RAII один

class ManagedResourceHandle { 
public: 
    ManagedResourceHandle(RawResourceHandle* rawHandle_) : rawHandle(rawHandle_) {}; 
    ~ManagedResourceHandle() {delete rawHandle; } 
    ... // omitted operator*, etc 
private: 
    RawResourceHandle* rawHandle; 
}; 

ManagedResourceHandle handle(createNewResource()); 
handle->performInvalidOperation(); 

В этом последнем случае, когда исключение генерируется и стек раскручивается, локальные переменные уничтожаются, которые гарантируют, что наш ресурс очищается и не течет.

+10

Очень ясно, а не только концептуально. Спасибо. –

+59

+1 для «это действительно страшное имя» – deinocheirus

+0

@the_mandrill: Я пробовал ideone.com/1Jjzuc эту программу. Но вызова деструктора нет. Tomdalling.com/blog/software-design/... говорит, что C++ гарантирует, что деструктор объектов в стеке будет вызываться, даже если выбрано исключение. Итак, почему деструктор здесь не выполнялся? Является ли мой ресурс утечкой или он никогда не будет освобожден или выпущен? – Destructor

1

Управление памятью вручную - это кошмар, который программисты изобретают способы избежать с момента изобретения компилятора. Языки программирования с сборщиками мусора облегчают жизнь, но ценой производительности. В этой статье - Eliminating the Garbage Collector: The RAII Way, инженер Toptal Питер Гудпед-Никлаус дает нам возможность заглянуть в историю сборщиков мусора и объясняет, как понятия собственности и заимствования могут помочь устранить сборщиков мусора без ущерба для их гарантий безопасности.

Смежные вопросы