[Примечания к C ++] Смарт-указатели C ++

Прочтите эту статью

1. Идеи дизайна умных указателей

2. Умный указатель прост в использовании.

3. Почему не рекомендуется использовать auto_ptr

4. Как выбрать, какой умный указатель использовать

Идеи дизайна умной указки

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

В этом примере из-за того, что генерируется исключение, оператор удаления не имеет возможности выполнить, что вызывает утечку памяти. Конечно, для этих десятков строк программы вы можете добавить оператор delete t к оператору catch, чтобы этого избежать.

Но что, если это инженерный проект с десятками W-линий? Я думаю, ты развалится! Так есть ли лучший способ? Ответ положительный.

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

Итак, мы подумали: если Test * t - это не обычная переменная-указатель, а объект класса, и этап освобождения динамической памяти реализован в деструкторе класса; тогда, пока переменная-указатель выходит из области видимости Деструктор будет вызван для достижения цели освобождения динамической памяти. Это идея умных указателей.

Согласно предыдущему предположению, нетрудно реализовать простой умный указатель следующим образом:

class SmartPointer 
{
    private:
        Test* ptr;
    public:
        SmartPointer(Test* p) 
        {
         ptr = p;
        }
         ~SmartPointer() //析构函数释放资源
         {
         delete p;
         }
};

Итак, как его использовать, просто нужно немного изменить на основе исходного кода, а именно:

[Примечания к C ++] Смарт-указатели C ++

Умный указатель C ++ прост в использовании

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

C ++ STL предоставляет нам четыре типа интеллектуальных указателей: auto_ptr, unique_ptr, shared_ptr и weak_ptr; среди них auto_ptr предоставляется в C ++ 98, и от него рекомендуется отказаться в C ++ 11. Что касается причины, я расскажу об этом позже; и unique_ptr, shared_ptr А weak_ptr был добавлен в STL с появлением C ++ 11.

Использование интеллектуальных указателей на самом деле несложно, как показано ниже:
[Примечания к C ++] Смарт-указатели C ++
[Примечания к C ++] Смарт-указатели C ++

Почему не рекомендуется использовать auto_ptr

Сначала посмотрите на следующее утверждение:

auto_ptr<int> px(new int(8));
auto_ptr<int> py;
py = px;

Что выполнит приведенный выше оператор присваивания? Если px и py являются обычными указателями, два указателя будут указывать на один и тот же динамически выделяемый объект int. Это неприемлемо, потому что программа может попытаться удалить один и тот же объект дважды: один раз по истечении срока действия px, а другой - по истечении срока действия py.Мы знаем, что одну и ту же память нельзя удалить дважды. Чтобы избежать этой проблемы, в основном используются следующие два метода:

  • Установите понятие собственности. Для конкретного объекта одновременно может принадлежать только один интеллектуальный указатель. Например, когда интеллектуальный указатель A указывает на объект x, когда выполняется B = A, исходный указатель A теряет право собственности на x, так что принадлежит только объект Конструктор интеллектуального указателя удалит объект, unique_ptr и auto_ptr используют эту стратегию.

  • Создавайте более умные указатели и отслеживайте количество интеллектуальных указателей, ссылающихся на определенные объекты. Это называется подсчетом ссылок. Например, при присвоении значения счетчик увеличится на 1, а когда срок действия указателя истечет, счетчик уменьшится на 1. Когда он уменьшается до 0, вызывается удаление. Это стратегия, используемая shared_ptr.

Конечно, такая же стратегия должна использоваться для конструкторов копирования.

Давайте посмотрим, почему рекомендуется отказаться от auto_ptr в C ++ 11. Посмотрите на следующий пример.
[Примечания к C ++] Смарт-указатели C ++
[Примечания к C ++] Смарт-указатели C ++
Из результатов работы программы, когда выполняется оператор присваивания py = px, программа вылетает при повторном доступе к px. Причина в том, что оператор присваивания py = px передает право собственности на объект с px на py, а px стал нулевым указателем. Конечно, повторный доступ к px будет ошибкой.

Итак, что произойдет, если вы используете unique_ptr или shared_ptr? Давайте проверим это. Давайте сначала посмотрим на ситуацию unique_ptr:
[Примечания к C ++] Смарт-указатели C ++
[Примечания к C ++] Смарт-указатели C ++
посмотрим, если вы используете unique_ptr, вы получите ошибку при компиляции в этом случае. То есть, даже если unique_ptr также использует модель владения, такую ​​как auto_ptr, программа не будет ждать при использовании unique_ptr. Сбой во время выполнения, показывая вам потенциальные ошибки во время компиляции

Хорошо, давайте посмотрим на ситуацию shared_ptr:
[Примечания к C ++] Смарт-указатели C ++
[Примечания к C ++] Смарт-указатели C ++
она работает нормально, когда используется shared_ptr, потому что shared_ptr использует подсчет ссылок. После выполнения оператора присваивания py = px px и py указывают на одну и ту же память, но когда вы освобождаете пространство, вам нужно судить заранее Следовательно, размер значения счетчика ссылок не вызывает ошибки многократного удаления объекта.

Как выбрать умную указку

Поняв эти типы интеллектуальных указателей, вы, естественно, можете подумать над вопросом: какой интеллектуальный указатель следует использовать в реальных проектных приложениях? В соответствии с характеристиками этих интеллектуальных указателей даются следующие предложения:

  • Если вы хотите использовать несколько указателей на один и тот же объект в программе, вы должны использовать shared_ptr; например, существует контейнер STL, содержащий указатели, и теперь алгоритм STL, который поддерживает операции копирования и присваивания, используется для управления элементами указателя контейнера, затем Вы должны использовать shared_ptr. Вы не можете использовать unique_ptr (ошибка компилятора) и auto_ptr (неопределенное поведение).

  • Если программе не нужно использовать несколько указателей на один и тот же объект, вы можете использовать unique_ptr; если функция использует new для выделения памяти и возвращает указатель на память, рекомендуется объявить ее возвращаемый тип как unique_ptr. Таким образом, право собственности передается на unique_ptr, который принимает возвращаемое значение, а интеллектуальный указатель будет отвечать за вызов удаления.

  • Когда выполняются условия, необходимые для unique_ptr, можно также использовать auto_ptr, но unique_ptr - лучший выбор.

подводить итоги

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

Рекомендуемая литература:

[Благополучие] Обмен видео с качественными онлайн-курсами, собранными мной (
Часть 1 ) [Лес протокола] Почтальон и почтовое отделение (Обзор сетевого протокола)
[Структура данных и алгоритм] Простое для понимания объяснение порядка битов
[Примечания C ++] Параллельное программирование на C ++ 11 (1) ) Начать путешествие по потоку
[Примечания C ++] Распространенные ошибки при использовании указателей C / C ++
[Примечания C ++] Подробное объяснение статических и динамических библиотек (включено)

Кодирование

Разработчик кода может предоставить вам простые для понимания технические статьи, которые упростят технологию!
[Примечания к C ++] Смарт-указатели C ++

Сосредоточьтесь на обмене сводкой знаний о стеке фоновых технологий сервера

Добро пожаловать, чтобы обратить внимание на общение и общий прогресс

рекомендация

отblog.51cto.com/15006953/2552128
рекомендация