Главная » Хабрахабр » [Перевод] Без new: Указатели будут удалены из C++

[Перевод] Без new: Указатели будут удалены из C++

Две недели назад в Джэксонвилле встречался комитет стандарта ISO C++. Сегодня я хочу представить короткую сводку и написать о революционном решении, принятом на собрании в Джэксонвилле. Для получения дополнительной информации я рекомендую к прочтению статью C++ больше не будет иметь указатели. Комитет по стандартизации языка принял решение о том, что указатели будут объявлены устаревшими в C++20 и с большой долей вероятности будут удалены из C++23.

Откровенно говоря, то, что кажется революционном, — всего лишь последний шаг длинной эволюции.

image

Указатели существуют в C++ с самого начала. Мы получили их из C. С самого начала развития C++ всегда была тенденция сделать управление указателями более безопасным без значительных потерь.

В C++98 мы получили std::auto_ptr для выражения исключительного владения. Но std::auto_ptr имел большой изъян. Когда вы копирует std::auto_ptr, владение ресурсом передавалось копии. Копирование выглядело как перемещение. Изображение ниже показывает неприятное поведение std::auto_ptr.
image

Это было очень плохо, приводило к множеству серьёзных багов. Поэтому мы получили std::unique_ptr в C++11, и объявили std::auto_ptr устаревшим в C++11, и окончательно удалили из C++17. Дополнительно мы получили std::shared_ptr и std::weak_ptr в C++11 для управления владением. Вы не можете копировать, но можете перемещать std::unique_ptr, и если копируете или присваиваете std::shared_ptr, счётчик ссылающихся указателей увеличивается. Посмотрите сюда:
image

Начиная с C++11 C++ имеет многопоточную библиотеку. Это делает управление std::shared_ptr достаточно сложным, потому что std::shared_ptr по определению разделяемое, но не потоко-безопасное. Только контрольная часть со счётчиками является потоко-безопасной, но не доступ к адресу контролируемого ресурса. Это значит, что изменение счётчика — атомарная операция, но вы не имеете гарантии, что ресурс будет удалён ровно один раз. По этой причине мы получаем в C++20 атомарные умные указатели: std::atomic_shared_ptr и std::atmic_weak_ptr. Про детали предложений комитета стандартизации читайте здесь: Атомарные умные указатели.

Теперь переходим к более интересным частям будущих стандартов C++20 и C++23. Указатели будет объявлены устаревшими в C++20 и удалены из C++23. Скажем три слова: Нет Новому New (NNN).

Но подождите, как же догма C++: Не платить за то, что вам не нужно. Как мы сможем программировать без указателей? Просто используйте std::unique_ptr. Из своего дизайна std::unique_ptr такой же быстрый и экономный, как и обычный указатель, и имеет явное преимущество — автоматическое управление ресурсом.

Ниже простой тест производительности.

// all.cpp #include <chrono>
#include <iostream> static const long long numInt= 100000000; int main(){ auto start = std::chrono::system_clock::now(); for ( long long i=0 ; i < numInt; ++i){ int* tmp(new int(i)); delete tmp; // std::shared_ptr<int> tmp(new int(i)); // std::shared_ptr<int> tmp(std::make_shared<int>(i)); // std::unique_ptr<int> tmp(new int(i)); // std::unique_ptr<int> tmp(std::make_unique<int>(i)); } std::chrono::duration<double> dur= std::chrono::system_clock::now() - start; std::cout << "time native: " << dur.count() << " seconds" << std::endl;
}

Эта программа выделяет и освобождает память для 100 миллионов int. Я использую указатели, std::shared_ptr и std::unique_ptr в двух вариациях. Я компилирую программу с и без максимальной оптимизации в Linux и в Windows. Получаются такие числа:
image

Две вариации std::unique_ptr на Linux и Windows показывают такую же производительность, как обычные указатели. За деталями этого теста обратитесь к моей прошлой статье: Потребление памяти и производительность умных указателей.

Честно говоря, мы используем указатели и, в частности, обычные указатели очень часто. Вопрос, должны ли вы использовать указатель, сводится к следующему: Кто владелец? К счастью, с помощью кода мы можем чётко выразить это.

  • Локальные объекты. Рантайм C++ как владелец автоматически управляет жизнью таких ресурсов. То же самое относится к глобальным объектам или членам класса. Справочники сводят это к области видимости.
  • Ссылки: я не владелец. Я только обеспечиваю, что ресурс не может быть пустым.
  • Обычные указатели: я не владелец. Я только ссылаюсь на ресурс, если он есть. Я не должен удалять ресурс.
  • std::unique_ptr: я исключительный владелец ресурса. Я могу явно освободить мой ресурс.
  • std::shared_ptr: я разделяю ресурс с другими std::shared_ptr. Я могу явно удалить мой разделяемый ресурс, если он больше никому не нужен.
  • std::weak_ptr: я не владелец ресурса, но я могу временно разделять ресурс при вызове моего метода std::weak_ptr::lock.

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


x

Ещё Hi-Tech Интересное!

Знакомство с выставками аудио- и видеотехники: от широкоформатных до профильных — часть вторая

В первой части нашего обзора мы начали рассказывать об интересных выставках аудио- и видеотехники, происходящих по всему миру. Сегодня — продолжаем знакомить вас с самыми известными мероприятиями в области Hi-Fi индустрии и музыкального оборудования. Кстати, если вам больше нравится микроформат ...

С МКС запустили спутник, охотящийся за космическим мусором

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