Jump to content

Умный указатель

(Перенаправлено из умных указателей )

В информатике интеллектуальный указатель — это абстрактный тип данных , который имитирует указатель , предоставляя дополнительные функции, такие как автоматическое управление памятью или проверка границ . Такие функции предназначены для уменьшения количества ошибок, вызванных неправильным использованием указателей, сохраняя при этом эффективность. Интеллектуальные указатели обычно отслеживают память, на которую они указывают, а также могут использоваться для управления другими ресурсами, такими как сетевые подключения и дескрипторы файлов . Интеллектуальные указатели были впервые популяризированы в языке программирования C++ в первой половине 1990-х годов как опровержение критики в отношении отсутствия в C++ автоматической сборки мусора . [ 1 ] [ 2 ]

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

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

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

Несмотря на то, что C++ популяризировал концепцию интеллектуальных указателей, особенно их разновидность с подсчетом ссылок , [ 3 ] непосредственный предшественник одного из языков, вдохновивших разработку C++, имел встроенные в язык ссылки с подсчетом ссылок. C++ частично был вдохновлен Simula67 . [ 4 ] Предком Simula67 была Simula I. Поскольку элемент Simula I аналогичен указателю C++ без null и поскольку процесс Simula I с фиктивным оператором в качестве тела активности аналогичен структуре C++ ( которая сама по себе аналогична CAR Hoare в записи современной на тот момент работе 1960-х годов ), ), Simula У меня были элементы с подсчетом ссылок (т. е. выражения-указатели, содержащие косвенность) на процессы (т. е. записи) нет позже сентября 1965 года, как показано в цитируемых ниже параграфах. [ 5 ]

На процессы можно ссылаться индивидуально. Физически ссылка на процесс — это указатель на область памяти, содержащую локальные для процесса данные и некоторую дополнительную информацию, определяющую его текущее состояние выполнения. Однако по причинам, указанным в разделе 2.2, ссылки на процессы всегда являются косвенными, через элементы, называемые элементами. Формально ссылкой на процесс является значение выражения типа element .

Значения элементов можно сохранять и извлекать путем присвоения и ссылок на переменные элемента , а также другими способами.
Язык содержит механизм, позволяющий сделать атрибуты процесса доступными извне, т. е. изнутри других процессов. Это называется удаленным доступом. Таким образом, процесс представляет собой структуру данных, на которую можно ссылаться.

Стоит отметить сходство между процессом, телом активности которого является фиктивный оператор, и концепцией записи, недавно предложенной К. А. Хоаром и Н. Виртом.

Поскольку C++ заимствовал Simula подход к выделению памяти — новое ключевое слово при выделении процесса/записи для получения нового элемента для этого процесса/записи — неудивительно, что C++ в конечном итоге возродил механизм интеллектуальных указателей Simula с подсчетом ссылок внутри элемента как хорошо.

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

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

SomeType* AmbiguousFunction();  // What should be done with the result?

Традиционно для устранения двусмысленности использовались соглашения об именах. [ 6 ] это подверженный ошибкам и трудоемкий подход. В C++11 в этом случае появился способ обеспечить правильное управление памятью путем объявления функции, возвращающей unique_ptr,

std::unique_ptr<SomeType> ObviousFunction();

Объявление типа возвращаемого значения функции как unique_ptr явно указывает на то, что вызывающая сторона становится владельцем результата, а среда выполнения C++ гарантирует, что память будет освобождена автоматически. До C++11 unique_ptr можно было заменить на auto_ptr , который сейчас устарел.

Создание новых объектов

[ редактировать ]

Чтобы облегчить распределение

std::shared_ptr<SomeType>

С++ 11 представил:

auto s = std::make_shared<SomeType>(constructor, parameters, here);

и аналогично

std::unique_ptr<some_type>

Начиная с С++ 14, можно использовать:

auto u = std::make_unique<SomeType>(constructor, parameters, here);

Почти во всех обстоятельствах предпочтительнее использовать эти средства, а не new ключевое слово. [ 7 ]

уникальный_ptr

[ редактировать ]

C++11 представляет std::unique_ptr, определенный в заголовке <memory>. [ 8 ]

А unique_ptr представляет собой контейнер для необработанного указателя, который unique_ptr Говорят, что он владеет. А unique_ptr явно предотвращает копирование содержащегося в нем указателя (как это происходит при обычном присваивании), но std::move функция может использоваться для передачи владения содержащимся указателем другому unique_ptr. А unique_ptr не может быть скопирован, поскольку его конструктор копирования и операторы присваивания явно удалены.

std::unique_ptr<int> p1(new int(5));
std::unique_ptr<int> p2 = p1;  // Compile error.
std::unique_ptr<int> p3 = std::move(p1);  // Transfers ownership. p3 now owns the memory and p1 is set to nullptr.

p3.reset();  // Deletes the memory.
p1.reset();  // Does nothing.

std::auto_ptr устарел в C++11 и полностью удален из C++17 . Конструктор копирования и операторы присваивания auto_ptr на самом деле не копируйте сохраненный указатель. Вместо этого они передают его , оставляя предыдущий auto_ptr объект пустой. Это был один из способов реализации строгой собственности, чтобы только один auto_ptr объект может владеть указателем в любой момент времени. Это означает, что auto_ptr не следует использовать там, где необходима семантика копирования. [ 9 ] [ нужна ссылка ] С auto_ptr уже существовал со своей семантикой копирования, его нельзя было обновить до указателя, предназначенного только для перемещения, без нарушения обратной совместимости с существующим кодом.

общий_ptr и слабый_ptr

[ редактировать ]

C++11 представляет std::shared_ptr и std::weak_ptr, определенный в заголовке <memory>. [ 8 ] C++11 также представляет std::make_shared ( std::make_unique был представлен в C++14) для безопасного выделения динамической памяти в парадигме RAII . [ 10 ]

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

std::shared_ptr<int> p0(new int(5));  // Valid, allocates 1 integer and initialize it with value 5.
std::shared_ptr<int[]> p1(new int[5]);  // Valid, allocates 5 integers.
std::shared_ptr<int[]> p2 = p1;  // Both now own the memory.

p1.reset();  // Memory still exists, due to p2.
p2.reset();  // Frees the memory, since no one else owns the memory.

А weak_ptr является контейнером для необработанного указателя. Он создается как копия shared_ptr. Существование или уничтожение weak_ptr копии shared_ptr не оказывают никакого влияния на shared_ptr или другие его копии. Ведь копии shared_ptr были уничтожены, все weak_ptr копии становятся пустыми.

std::shared_ptr<int> p1 = std::make_shared<int>(5);
std::weak_ptr<int> wp1 {p1};  // p1 owns the memory.

{
  std::shared_ptr<int> p2 = wp1.lock();  // Now p1 and p2 own the memory.
  // p2 is initialized from a weak pointer, so you have to check if the
  // memory still exists!
  if (p2) {
    DoSomethingWith(p2);
  }
}
// p2 is destroyed. Memory is owned by p1.

p1.reset();  // Free the memory.

std::shared_ptr<int> p3 = wp1.lock(); 
// Memory is gone, so we get an empty shared_ptr.
if (p3) {  // code will not execute
  ActionThatNeedsALivePointer(p3);
}

Поскольку реализация shared_ptr использует подсчет ссылок , циклические ссылки могут стать проблемой. Циркуляр shared_ptr цепочку можно разорвать, изменив код так, чтобы одна из ссылок была weak_ptr.

Несколько потоков могут безопасно одновременно обращаться к различным shared_ptr и weak_ptr объекты, указывающие на один и тот же объект. [ 11 ]

Объект, на который ссылаются, должен быть защищен отдельно, чтобы обеспечить потокобезопасность .

shared_ptr и weak_ptr основаны на версиях, используемых библиотеками Boost . [ нужна ссылка ] Технический отчет C++ 1 (TR1) впервые представил их в стандарте как общие утилиты , но в C++11 добавлено больше функций, как и в версии Boost.

Другие типы интеллектуальных указателей

[ редактировать ]

Существуют и другие типы интеллектуальных указателей (которые не входят в стандарт C++), реализованные в популярных библиотеках C++ или пользовательских STL . Некоторые примеры включают указатель опасности. [ 12 ] и навязчивый указатель. [ 13 ] [ 14 ]

См. также

[ редактировать ]
  1. ^ Клайн, Маршалл (сентябрь 1997 г.). «Часто задаваемые вопросы по C++ Lite, посвященные интеллектуальным указателям с подсчетом ссылок и семантике ссылок при копировании при записи в часто задаваемых вопросах по управлению бесплатным хранилищем» . cis.usouthal.edu . Проверено 6 апреля 2018 г.
  2. ^ Колвин, Грегори (1994). «Предложение по стандартизации counted_ptr в стандартной библиотеке C++» (PDF) . open-std.org . Проверено 6 апреля 2018 г.
  3. ^ Клабник, Стив; Николс, Кэрол (2023) [2018]. «15. Умные указатели». Язык программирования Rust (2-е изд.). Сан-Франциско, Калифорния, США: No Starch Press, Inc., стр. 315–351. ISBN  978-1-7185-0310-6 . (xxix+1+527+3 страницы)
  4. ^ Страуструп, Бьерн. «История C++: 1979–1991» (PDF) . Проверено 6 апреля 2018 г.
  5. ^ Даль, Оле-Йохан; Найгаард, Кристен (сентябрь 1966 г.). «SIMULA — язык моделирования на основе ALGOL» (PDF) . фолк.уйо.но. ​Проверено 6 апреля 2018 г.
  6. ^ «Руководство Taligent по разработке программ», раздел «Используйте специальные имена для копирования, создания и внедрения процедур» .
  7. ^ Саттер, Херб (20 апреля 2013 г.). «Отчет о поездке: встреча ISO C++ весной 2013 г.» . isocpp.org . Проверено 14 июня 2013 г.
  8. ^ Jump up to: а б ИСО 14882:2011 20.7.1
  9. ^ CERT Стандарт безопасного кодирования C++
  10. ^ ИСО 14882:2014 20.7.1
  11. ^ «boost::shared_ptr потокобезопасность» . (Примечание. Формально не распространяется на std::shared_ptr, но считается, что он имеет те же ограничения на потоки.)
  12. ^ «folly/Hazptr.h на главной · facebook/folly» . github.com .
  13. ^ «Boost.SmartPtr: библиотека интеллектуальных указателей — 1.81.0» . boost.org .
  14. ^ «EASTL/intrusive_ptr.h в мастере · Electronicarts/EASTL» . github.com .

Дальнейшее чтение

[ редактировать ]
[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 5124128e7c8da4a919037e197bde8b9a__1717446180
URL1:https://arc.ask3.ru/arc/aa/51/9a/5124128e7c8da4a919037e197bde8b9a.html
Заголовок, (Title) документа по адресу, URL1:
Smart pointer - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)