Поделиться через


Интеллектуальные указатели (самомоднейшее C++)

В современных программирования C++, включает стандартную библиотеку смарт-указатели, которые используются для обеспечения программ, могут свободно памяти и утечки ресурсов и безопасных исключений.

Использование смарт-указатели

Смарт-указатели, определены в std пространство имен в <memory> файл заголовка.Они имеют решающее значение для RAII или Initialialization является приобретение ресурсов идиом программирования.Основной целью данный идиом является убедитесь в том, что приобретение ресурсов происходит в то же время, инициализированный объект таким образом, все ресурсы объекта создаются и подготовить в одной строке кода.На практике основной принцип RAII — предоставить владельцем всех ресурсов, выделенных в куче — например, динамического выделения памяти или системных дескрипторов объектов — объект выделен стек, деструктор которого содержит код для удаления или освобождения ресурса, а также любой связанный код очистки.

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

В следующем примере сравниваются объявления raw указателя для объявления указателей.

void UseRawPointer()
{
    // Using a raw pointer -- not recommended.
    Song* pSong = new Song(L"Nothing on You", L"Bruno Mars"); 

    // Use pSong...

    // Don't forget to delete!
    delete pSong;   
}


void UseSmartPointer()
{
    // Declare a smart pointer on stack and pass it the raw pointer.
    unique_ptr<Song> song2(new Song(L"Nothing on You", L"Bruno Mars"));

    // Use song2...
    wstring s = song2->duration_;
    //...

} // song2 is deleted automatically here.

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

Доступ инкапсулированные указателя с помощью операторов знакомые указатель -> и *, перегружающий класса смарт-указатель возвращает инкапсулированное raw указатель.

Идиома смарт-указатель C++ напоминает создание объекта в языках, таких как C#: создать объект и подождите, пока система заботу удаление в нужное время.Разница заключается в том, что нет отдельного сборщика мусора выполняется в фоновом режиме; памяти осуществляется с помощью стандарта C++ областей правил таким образом, среде выполнения быстрее и эффективнее.

Важное примечаниеВажно

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

В следующем примере показано как unique_ptr смарт-указатель типа из библиотеки стандартных шаблонов может использоваться для инкапсуляции указатель для больших объектов.


class LargeObject
{
public:
    void DoSomething(){}
};

void ProcessLargeObject(const LargeObject& lo){}
void SmartPointerDemo()
{    
    // Create the object and pass it to a smart pointer
    std::unique_ptr<LargeObject> pLarge(new LargeObject());

    //Call a method on the object
    pLarge->DoSomething();

    // Pass a reference to a method.
    ProcessLargeObject(*pLarge);

} //pLarge is deleted automatically when function block goes out of scope.

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

  1. Объявите смарт-указатель как автоматический (local).(Не используйте new или malloc выражения на смарт-сам указатель.)

  2. В параметр типа укажите тип, на который указывает на инкапсулированные указателя.

  3. Передать исходный указатель new-ed объекта в конструкторе интеллектуального указателя.(Некоторые функции программы или смарт-указатель, конструкторы это сделать для вас).

  4. Используйте перегруженный -> и * операторы для доступа к объекту.

  5. Позволяет удалить объект смарт-указатель.

Смарт-указатели предназначены быть предельно эффективными так памяти и производительности.Например, элемент данных только в unique_ptr является инкапсулированным указателя.Это означает, что unique_ptr того же размера, как этот указатель байтов четыре или восемь байт.К инкапсулированным указателя с помощью смарт-указатель, перегруженные *-> операторы не значительно медленнее, чем непосредственный доступ к необработанным указатели.

Смарт-указатели имеют свои собственные функции-члены, к которым можно получить с помощью нотации «точка».Например некоторые смарт-указатели STL имеют функцию-член reset, освобождает владельца указателя.Это полезно, когда требуется освободить память, принадлежащие смарт-указатель перед смарт-указатель выходит за область действия, как показано в следующем примере.

void SmartPointerDemo2()
{
    // Create the object and pass it to a smart pointer
    std::unique_ptr<LargeObject> pLarge(new LargeObject());

    //Call a method on the object
    pLarge->DoSomething();

    // Free the memory before we exit function block.
    pLarge.reset();

    // Do some other work...

}

Смарт-указатели обычно предоставляют возможность непосредственного доступа к их исходному указателю.Смарт-указатели STL у get функции-члена для этой цели и CComPtr имеет открытый p член класса.Предоставляя прямой доступ к базовым указателя, можно использовать смарт-указатель для управления памятью в коде и передавать исходный указатель на код, который не поддерживает смарт-указатели.

void SmartPointerDemo4()
{
    // Create the object and pass it to a smart pointer
    std::unique_ptr<LargeObject> pLarge(new LargeObject());

    //Call a method on the object
    pLarge->DoSomething();

    // Pass raw pointer to a legacy API
    LegacyLargeObjectFunction(pLarge.get());    
}

Виды смарт-указатели

В следующем разделе перечислены различные виды смарт-указатели, которые доступны в среде программирования Windows и описание их использования.

  • Стандарт C++ библиотека смарт-указатели
    Используйте эти смарт-указатели как первый вариант для инкапсуляции указатели на обычные старые объекты C++ (POCO).

    • unique_ptr
      Позволяет точно один владелец базового указателя.Использовать в качестве элемента по умолчанию POCO не известно то, что требуется, shared_ptr.Могут быть перемещены в новый владелец, но не копируются или совместно.Заменяет auto_ptr, который является устаревшим.Сравнение с boost::scoped_ptr.unique_ptrявляется небольшим и эффективным; размер составляет один указатель и поддерживает rvalue ссылки для быстрой вставки и извлечения из коллекции библиотеки STL.Файл заголовка: <memory>.Дополнительные сведения см. в разделах Практическое руководство. Создание и использование экземпляров unique_ptr и unique_ptr Class.

    • shared_ptr
      Со счетчиком ссылок смарт-указатель.Следует использовать, когда нужно назначить один исходный указатель нескольких владельцев, например, когда возвращать копию указатель из контейнера, но сохранить исходное.Исходный указатель не удаляется до всех shared_ptr владельцев выходе за пределы области действия или в противном случае заданные настройки владельца.Имеет размер двух указателей; один объект и блок общий элемент управления, который содержит счетчик ссылок.Файл заголовка: <memory>.Дополнительные сведения см. в разделах Практическое руководство. Создание и использование экземпляров shared_ptr и shared_ptr Class.

    • weak_ptr
      Особой смарт-указатель для использования в сочетании с shared_ptr.A weak_ptr предоставляет доступ к объекту, который владеет одним или несколькими shared_ptr экземпляров, но не участвует в подсчет ссылок.Используется, когда необходимо наблюдать за объектом, но не требуют его оставаться в активном состоянии.Требуется в некоторых случаях прерывание циклических ссылок между shared_ptr экземпляры.Файл заголовка: <memory>.Дополнительные сведения см. в разделах Практическое руководство. Создание и использование экземпляров weak_ptr и weak_ptr Class.

  • Смарт-указатели для COM-объектов (классический Windows программирование)
    При работе с COM-объектами, перенос указателей интерфейса смарт-указатель, соответствующего типа.Active Template Library (ATL) определяет несколько смарт-указатели для различных целей.Можно также использовать _com_ptr_t тип смарт-указатель, который компилятор использует при создании классов-оболочек из TLB-файлов.Это лучший выбор, когда не требуется включать файлы заголовков ATL.

  • Смарт-указатели ATL POCO объектов
    В дополнение к смарт-указатели для COM-объектов ATL также определяет смарт-указатели и коллекций смарт-указатели для обычного старые объекты C++.В классической программирования для Windows, эти типы являются полезной альтернативой коллекциях STL особенно когда переноса кода не требуется или необходимо смешать модели программирования, STL и ATL.

    • Класс CAutoPtr
      Смарт-указатель, который обеспечивает уникальное владения, передача прав владения на копию.Сравним с устаревшей std::auto_ptr класса.

    • Класс CHeapPtr
      Смарт-указатель для объектов, которые выдаются с помощью c malloc функции.

    • Класс CAutoVectorPtr
      Смарт-указатель для массивов, выделенной с помощью new[].

    • Класс CAutoPtrArray
      Класс, инкапсулирующий массив CAutoPtr элементов.

    • Класс CAutoPtrList
      Класс, который инкапсулирует методы управления список CAutoPtr узлов.

См. также

Другие ресурсы

Добро пожаловать в C++ (современные C++)

Справочник по языку C++

Справочник по стандартной библиотеки C++

общие сведения: Управление памятью в C++