Что такое умный указатель и когда я должен его использовать?

.*

. - любой символ, * означает повторяющееся ноль или более раз.

1664
задан 0x6900 13 July 2015 в 05:07
поделиться

6 ответов

ОБНОВЛЕНИЕ

Этот ответ довольно стар, и так описывает то, что было 'хорошо' в то время, который был интеллектуальными указателями, обеспеченными библиотекой Boost. Начиная с C++ 11, стандартная библиотека обеспечила достаточные типы интеллектуальных указателей, и таким образом, необходимо одобрить использование [1 120] std::unique_ptr , std::shared_ptr и std::weak_ptr .

существует также std::auto_ptr . Это очень похоже на ограниченный по объему указатель, за исключением того, что это также имеет "специальную" опасную способность, которая будет скопирована —, который также неожиданно передает владение! Это удерживается от использования в новейших стандартах, таким образом, Вы не должны использовать его. Используйте std::unique_ptr вместо этого.

std::auto_ptr<MyObject> p1 (new MyObject());
std::auto_ptr<MyObject> p2 = p1; // Copy and transfer ownership. 
                                 // p1 gets set to empty!
p2->DoSomething(); // Works.
p1->DoSomething(); // Oh oh. Hopefully raises some NULL pointer exception.
<час>

СТАРЫЙ ОТВЕТ

интеллектуальный указатель А является классом, который обертывает 'сырые данные' (или 'пустой') указатель C++, для управления временем жизни указываемого объекта. Нет никакого единственного типа интеллектуального указателя, но все они пытаются абстрагировать необработанный указатель практическим способом.

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

С необработанными указателями, программист должен явно уничтожить объект, когда это больше не полезно.

// Need to create the object to achieve some goal
MyObject* ptr = new MyObject(); 
ptr->DoSomething(); // Use the object in some way
delete ptr; // Destroy the object. Done with it.
// Wait, what if DoSomething() raises an exception...?

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

SomeSmartPtr<MyObject> ptr(new MyObject());
ptr->DoSomething(); // Use the object in some way.

// Destruction of the object happens, depending 
// on the policy the smart pointer class uses.

// Destruction would happen even if DoSomething() 
// raises an exception

самая простая используемая политика включает объем интерфейсного объекта интеллектуального указателя, такой, как реализовано [1 125] boost::scoped_ptr или std::unique_ptr .

void f()
{
    {
       std::unique_ptr<MyObject> ptr(new MyObject());
       ptr->DoSomethingUseful();
    } // ptr goes out of scope -- 
      // the MyObject is automatically destroyed.

    // ptr->Oops(); // Compile error: "ptr" not defined
                    // since it is no longer in scope.
}

Примечание, что std::unique_ptr экземпляры не могут быть скопированы. Это препятствует тому, чтобы указатель был удален многократно (неправильно). Можно, однако, передать ссылки на него вокруг к другим функциям, которые Вы вызываете.

std::unique_ptr с полезны, когда Вы хотите связать время жизни объекта к конкретному блоку кода, или если Вы встроили его как членские данные в другом объекте, время жизни того другого объекта. Объект существует, пока из содержания блока кода не выходят, или пока содержание объекта самостоятельно не уничтожается.

А более сложная политика интеллектуального указателя включает подсчет ссылок указатель. Это действительно позволяет указателю быть скопированным. Когда последняя "ссылка" на объект уничтожается, объект удален. Эта политика проводится [1 127] boost::shared_ptr и std::shared_ptr .

void f()
{
    typedef std::shared_ptr<MyObject> MyObjectPtr; // nice short alias
    MyObjectPtr p1; // Empty

    {
        MyObjectPtr p2(new MyObject());
        // There is now one "reference" to the created object
        p1 = p2; // Copy the pointer.
        // There are now two references to the object.
    } // p2 is destroyed, leaving one reference to the object.
} // p1 is destroyed, leaving a reference count of zero. 
  // The object is deleted.

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

существует один недостаток к ссылке считаемые указатели — возможность создания повисшей ссылки:

// Create the smart pointer on the heap
MyObjectPtr* pp = new MyObjectPtr(new MyObject())
// Hmm, we forgot to destroy the smart pointer,
// because of that, the object is never destroyed!

Другая возможность создает циклические ссылки:

struct Owner {
   std::shared_ptr<Owner> other;
};

std::shared_ptr<Owner> p1 (new Owner());
std::shared_ptr<Owner> p2 (new Owner());
p1->other = p2; // p1 references p2
p2->other = p1; // p2 references p1

// Oops, the reference count of of p1 and p2 never goes to zero!
// The objects are never destroyed!

Для работы вокруг этой проблемы оба Повышения и C++ 11 определили weak_ptr для определения слабой (бесчисленной) ссылки на shared_ptr.

1803
ответ дан klutt 13 July 2015 в 05:07
поделиться

Определения, предоставленные Chris, Sergdev и Llyod, корректны. Я предпочитаю более простое определение хотя, только для хранения моей жизни простой: интеллектуальный указатель является просто классом, который перегружается -> и * операторы. Что означает, что Ваш объект семантически похож на указатель, но можно заставить его сделать путь вещи вентилятора, включая подсчет ссылок, автоматическое разрушение и т.д. shared_ptr и auto_ptr достаточно в большинстве случаев, но приходит с их собственным набором маленьких особенностей.

39
ответ дан NathanOliver 13 July 2015 в 05:07
поделиться

http://en.wikipedia.org/wiki/Smart_pointer

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

8
ответ дан Jorge Ferreira 13 July 2015 в 05:07
поделиться

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

большинство наиболее часто используемых интеллектуальных указателей std::tr1::shared_ptr (или boost::shared_ptr), и, реже, std::auto_ptr. Я рекомендую регулярное использование shared_ptr.

shared_ptr очень универсально и имеет дело с большим множеством сценариев распоряжения, включая случаи, куда объекты должны быть "переданы через границы DLL" (общий случай кошмара, если отличающийся libc с используются между Вашим кодом и DLLs).

16
ответ дан Chris Jester-Young 13 July 2015 в 05:07
поделиться

Интеллектуальный указатель является подобным указателю типом с некоторой дополнительной функциональностью, например, автоматическим освобождением памяти, подсчетом ссылок и т.д.

, Маленькое введение доступно на Интеллектуальных указателях страницы - Что, Да ведь Который? .

Один из простого типа интеллектуального указателя std::auto_ptr (глава 20.4.5 стандарта C++), который позволяет освобождать память автоматически, когда это из объема и который более устойчив, чем простое использование указателя, когда исключения выдаются, хотя менее гибкий.

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

Предмет покрыт подробно в книге "Шаблоны C++: полное руководство" David Vandevoorde, Nicolai M. Josuttis , глава Глава 20. Интеллектуальные указатели. Некоторые темы покрыли:

107
ответ дан Varaquilex 13 July 2015 в 05:07
поделиться

Интеллектуальный указатель похож на обычный (введенный) указатель, как "символ* ", кроме тех случаев, когда сам указатель выходит из объема тогда, на что это указывает, удален также. Можно использовать его как Вы, был бы регулярный указатель, при помощи"->", но не, если Вам нужен фактический указатель на данные. Для этого можно использовать "& *ptr".

Это полезно для:

  • Объекты, которые должны быть выделены с новым, но что требуется иметь то же время жизни как что-то на том стеке. Если объект будет присвоен интеллектуальному указателю, то они будут удалены когда выходы программы та функция/блок.

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

Вы май не хотят использовать интеллектуальный указатель когда:

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

См. также:

28
ответ дан Community 13 July 2015 в 05:07
поделиться
Другие вопросы по тегам:

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