Удаленные функции C++17
C++17 позволяет писать простой, понятный и выразительный код. Вот некоторые из возможностей, представленных в C++17:
- Вложенные пространства имен
- Объявление переменной в if и switch
- оператор if constexpr
- Структурированные привязки
- Свернуть выражения
- Прямая инициализация списка перечислений
В новой версии C++17 представлено много новых функций, но некоторые возможности удалены или объявлены устаревшими. Они перечислены ниже:
- Удаление устаревшего оператора ++
- Удаление регистров
- Удаление auto_ptr
- Триграфы
- бросить (идентификатор типа)
- Поддержка распределителя в std::function
- std::pointer_to_unary_function и std::pointer_to_binary_function
- std::binder1st и std::binder2nd
- std::bind1st и std::bind2nd
- Другие функции.
Давайте начнем подробно обсуждать эти функции.
1. Удаление устаревшего оператора ++: Постфиксные и префиксные выражения Increment (++) теперь недействительны для логических операндов, поскольку префиксный и постфиксный оператор ++ были перегружены для типа bool, но в обоих случаях возвращаемое значение для логического аргумента правда. Тип bool не поддерживает полный набор арифметических типов. С момента запуска C++98 этого изменения ждали. В новой версии C++17 он больше не считается арифметическим типом, и эти операторы объявлены устаревшими.
Альтернативы: В качестве альтернативы можно использовать std::exchange , но только там, где допустимо использование постфиксного оператора. Функция обмена заменяет значение объекта новым значением и возвращает старое значение объекта.
2. Удаление регистров: Давным- давно ключевое слово register в C++11 устарело. Ключевое слово register указывает или дает подсказку компилятору, что переменная может быть помещена в регистр для быстрого доступа, или эти переменные могут интенсивно использоваться, чтобы он мог выполнять оптимизацию, сохраняя их в регистре ЦП. Но компиляторы выполняют неявную оптимизацию, и подсказка использовалась редко. Поэтому в новой версии ключевое слово register удалено, хотя ключевое слово по-прежнему зарезервировано для будущих версий.
Синтаксис:
register string s = "Register on GfG"
Альтернативы: нет альтернативы для регистрации, поскольку компилятор выполняет ту же работу автоматически.
3. Удаление auto_ptr: auto_ptr использовался для создания интеллектуального указателя для обработки времени жизни объекта. Он является владельцем объекта, на который ссылается. Когда объект уничтожается, auto_ptr также автоматически уничтожается. Этот интеллектуальный указатель незаметно крадет право собственности на управляемый объект в его конструкторе копирования и копирует назначение из правого аргумента. В результате копия не совпадает с исходным объектом интеллектуального указателя. Из-за этой семантики копирования auto_ptr не работает как CopyConstructible и, следовательно, устарел.
Альтернативы: auto_ptr можно легко заменить на, unique_ptr который также является интеллектуальным указателем с аналогичной работой, но с повышенной безопасностью. Он был представлен в C++11 как прямая замена auto_ptr , поскольку он предоставляет новые функции (удаления) и поддержку массивов. Более того, он допускает только одного владельца указателя ссылки. Таким образом, при использовании unique_ptr для одного ресурса может быть только один unique_ptr , и когда он уничтожается, ресурс автоматически запрашивается. Если будет попытка сделать копию unique_ptr , это вызовет ошибку времени компиляции.
Пример:
unique_ptr<T> p1 (new T); unique_ptr<T> p2 = p1; // Error: can"t copy unique_ptr
4. Триграфы: Триграфы представляют собой группу из трех персонажей. По сути, это специальная последовательность символов, которая используется в качестве альтернативы некоторым символам. Он представлен двумя вопросительными знаками.
Пример:
??- produces ~ ??= produces # ??/ produces ??’ produces ^ ??( produces [ ??) produces ] ??! produces | ??< produces { ??> produces }
Но они вызывают много путаницы, поскольку анализируются перед комментариями и поэтому удаляются в последней версии.
Альтернативы: C++17 не предоставляет никаких альтернатив для Trigraph, поскольку современные клавиатуры имеют все эти функции. Кроме того, он производит много ошибок в коде.
5. throw(typeid): Если какая-либо функция объявлена с типом T, указанным в ее спецификации исключений, функция может генерировать исключения для этого типа или производного от него типа. Это версия спецификации динамического исключения без генерации, которая устарела и теперь удалена. Он был заменен на noexcept , что имеет более ясное значение.
Синтаксис:
throw(typeid, typeid, ...)
Пример:
void throwsInt(int x) throw(int) { cout<<"throw function replaced with noexcept :)"; if (x == 0) { throw 1; } }
Альтернативы: как упоминалось выше, у throw может быть лучшая альтернатива с noexcept . Он указывает, могут ли функции генерировать исключения или нет, без указания их типа. Но используйте его только тогда, когда вызов функции не может вызвать ошибку, иначе программа завершится.
6. Поддержка распределителя в std::function: несколько конструкторов позволяют указать распределитель, используемый для выделения внутренней памяти. У std::function также есть конструкторы, которые принимают аргумент распределителя, но семантика неясна, и есть технические сбои с сохранением распределителя в контексте со стертым типом и последующим восстановлением этого распределителя позже для любых выделений, необходимых во время копирования. назначение. Поэтому эти перегрузки конструктора были удалены в C++17.
Альтернативы: в C++ нет такой функции, которая заменяет распределитель.
7. std::pointer_to_unary_function, std::pointer_to_binary_function: объекты функций std::pointer_to_unary_function , std::pointer_to_binary_function , которые действуют как оболочки вокруг унарных или бинарных функций. Эти функции включают в себя конструктор , который создает новый объект pointer_to_unary_function с предоставленной функцией и функцией operator(), которая вызывает хранимую функцию.
Альтернативы: эти две функции std::function и std::ref заменяют std::pointer_to_unary_function , std::pointer_to_binary_function .
8. std::binder1st и std::binder2nd: это функциональные объекты, которые связывают аргумент с бинарной функцией. Значение параметра передается объекту во время построения и сохраняется внутри объекта. Всякий раз, когда объект функции вызывается через функцию operator(), сохраненное значение передается как один из аргументов, а другой аргумент передается как аргумент оператора(). Результирующий функциональный объект является унарной функцией.
- binder1st: связывает первый параметр со значением, заданным во время создания объекта.
- binder2nd: привязывает второй параметр к значению, заданному во время создания объекта.
Альтернативы: Lambdas , std::bind — это две функции, которые могут быть альтернативой для binder1st и binder2nd.
9. std::bind1st и std::bind2nd: это вспомогательные функции, которые создают экземпляры std::binder1st или std::binder2nd, которые связывают заданный аргумент с первым или вторым параметром заданного объекта бинарной функции. Но они бесполезны с введением лямбд в C++11, поэтому они устарели.
10. Другие функции:
- стд::mem_fun_t,
- std::mem_fun1_t
- std::const_mem_fun_t
- std::const_mem_fun1_t
- std::mem_fun_ref_t
- std::mem_fun1_ref_t
- std::const_mem_fun_ref_t
- std::const_mem_fun1_ref_t
Это функциональные объекты, которые обертывают указатель на функцию-член без параметров или с одним параметром. Экземпляр класса, чья функция-член для вызова передается как указатель на operator(), т. е. объект, чья функция-член для вызова передается по указателю на оператор вызова для последнего, передается как ссылка. Они устарели, потому что они ограничены функциями-членами либо без аргументов, либо только с одним аргументом, а для обработки указателей или ссылок на экземпляр класса требуются разные функции и объекты функций.
Альтернативы: альтернативой вышеперечисленным функциям является std::mem_fn , которая может обрабатывать функции-члены с любым количеством переменных и не только ссылками или указателями на объекты, но и интеллектуальными указателями.