Главная » Просмотр файлов » С. Мейерс - Эффективный и современный C++

С. Мейерс - Эффективный и современный C++ (1114942), страница 52

Файл №1114942 С. Мейерс - Эффективный и современный C++ (С. Мейерс - Эффективный и современный C++) 52 страницаС. Мейерс - Эффективный и современный C++ (1114942) страница 522019-05-08СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 52)

Цель этого действия заключается в том, чтобы однафункция (которой передаются параметры) получила в точности те же объекты, которыепереданы другой функции (которая выполняет передачу). Тем самым исключается пере­дача параметров по значению, поскольку при этом выполняется копирование исходнопереданных объектов; мы же хотим, чтобы передающая функция была способна рабо­тать с изначально переданными объектами. Указатели также исключаются, поскольку мыне хотим заставлять вызывающий код передавать указатели. Когда речь идет о передачеобщего назначения, мы работаем с параметрами, представляющими собой ссылки.Прямая передача означает, что мы передаем не просто объекты, но и их основныехарактеристики: их типы, являются они lvalue или rvalue, объявлены они как const илиvo la t i le.

В сочетании с наблюдением о том, что мы будем иметь дело со ссылочнымипараметрами, это означает, что мы будем использовать универсальные ссылки (см. раз­дел 5.2), поскольку только параметры, являющиеся универсальными ссылками, хранят ин­формацию о том, какие аргументы - являющиеся lvalue или rvalue - были им переданы.Предположим, что у нас есть некоторая функция f и мы хотели бы написать функцию(по правде говоря, шаблон функции), которая выполняет передачу ей.

Ядро того, что намнадо, имеет следующий вид:template<typename Т>void fwd ( T&& param){11 Принимает любой аргументf ( std : : forward<Т> (param) ) ; / / Передача аргументавfПередающие функции по своей природе являются обобщенными. Шаблон fwd, на­пример, принимает аргумент любого типа, и он передает все, что бы ни получил. Логи­ческим продолжением этой обобщенности являются передающие функции, являющиесяне просто шаблонами, а шаблонами с произвольным количеством аргументов (вариатив­ными шаблонами (variadic templates)).

Вариативная разновидность fwd выглядит следую­щим образом:template<typename . . . Ts>void fwd ( Ts&& . . . params )11 Принимает любые аргументы{f ( std : : forward<Ts> ( pararns ) . . . ) ; / / Передача аргументов в fЭту разновидность вы встретите, помимо прочих мест, в функциях размещения стан­дартных контейнеров (см. раздел 8.2) и в фабричных функциях для интеллектуальныхуказателей, s t d : : ma ke_shared и std : : ma ke_un ique (см. раздел 4.4).Для заданной целевой функции f и нашей передающей функции fwd прямая передачазавершается неудачей, если вызов функции f с конкретным аргументом выполняет нечтоодно, а вызов fwd с теми же аргументами - нечто иное:212Глава 5. Rvаluе-ссылки, семантика перемещений и прямая передачаf ( express i on ) ;/ / Если этот вызов выполняет что-то одно,fwd ( expression ) ; / / а этот - нечто иное, прямая передача/ / функцией fwd функции f неудачнаК такой неудаче могут привести несколько видов аргументов.

Знать эти аргументыи то, как с ними работать, весьма важно, так что начнем наш тур по аргументам, которыене могут быть переданы с помощью прямой передачи.Ин ици ализаторы в ф и rу р ных с кобкахПредположим, что f объявлена следующим образом:void f ( const std : : vector<int>& v ) ;В этом случае вызов f с инициализаторами в фигурных скобках компилируется:1 1 ОК, " { 1 , 2 , 3 } " неявно преобразуется11 в s t d : : vector<int>f ( { l, 2, 3 }) ;Однако передача того же инициализатора в фигурных скобках функции fwd не компи­лируется:fwd ( { 1 , 2 , 3 } ) ;/ / Ошибка ! Код не компилируется 1Дело в том, что применение инициализаторов в фигурных скобках - один из случаев,когда прямая передача терпит неудачу.Все такие случаи отказов имеют одну и ту же причину. В непосредственном вызовеf (таком, как f ( { 1 , 2 , 3 ) ) ) компиляторы видят аргументы, переданные в точке вызова,и видят типы параметров, объявленные функцией f.

Они сравнивают аргументы в точ­ке вызова с объявлениями параметров на предмет совместимости и при необходимостивыполняют неявное преобразование, чтобы вызов был успешным. В приведенном вышепримере они генерируют временный объект типа s t d : : vect o r < i n t > из { 1 , 2 , 3 ) , так чток параметру v функции f привязывается объект типа s t d : : vector<int>.При косвенном вызове f с помощью шаблона передающей функции fwd компиляторыбольше не сравнивают аргументы, переданные в точке вызова fwd, с объявлениями пара­метров в f. Вместо этого они вь1водят типы аргументов, переданных в fwd, и сравниваютвыведенные типы с объявлениями параметров в f. Прямая передача оказывается неудач­ной, если происходит что-то из следующего.•Компиляторы неспособны вывести типодного или нескольких параметров fwd.В этом случае код не компилируется.•Компиляторы выводят "неверный" тип одного или нескольких параметров fwd.Здесь "неверный" может означать как то, что инстанцирование fwd не компилиру­ется с выведенными типами, так и то, что вызов f с использованием выведенныхтипов fwd ведет себя не так, как непосредственный вызов f с аргументами, пере­данными в fwd.

Одним источником такого отклонения в поведении могла бы бытьситуация, когда у f имеется перегрузка, и из-за "некорректного" вывода типов этаперегрузка f, вызываемая в fwd, отличалась бы от перегруженной функции f, ис­пользуемой при непосредственном вызове.5.8.Поэнакомыесь с случаями некорректной работы прямой передачи213В приведенном выше вызове " fwd ( { 1 , 2 , 3 } ) " проблема заключается в том, что пере­дача инициализатора в фигурных скобках параметру шаблона функции, не объявленно­му как std : : i n i t ia l i zer_ l i st, заставляет его быть, как предписывает стандарт, "не вы­водимым контекстом': На простом человеческом языке это означает, что компиляторамзапрещено выводить тип для выражения { 1 , 2 , 3 } в вызове fwd, поскольку параметр fwdне объявлен как std : : i n i t i a l i zer_l i s t . Не имея возможности вывести тип параметраfwd, компиляторы, понятно, вынуждены отклонять такой вызов.Интересно, что в разделе 1 .2 поясняется, что вывод типа для переменных auto, ини­циализированных с помощью инициализатора в фигурных скобках, успешен.

Такие пере­менные считаются объектами типа s t d : : i n i t i a l i zer_ l i s t , и это обеспечивает простойобходной путь для случаев, когда тип передающей функции должен быть выведен какstd : : i n i t i al i zer_ l i s t : объявить локальную переменную как auto, а затем передать еев передающую функцию:auto ilfwd ( i l ) ;={ 1,2,3 } ; // Тип il выводится как11 s td : : initiali zer l ist<int>// ОК, прямая передача il в fо и NULL в качес тве нулевых указателейВ разделе 3.2 поясняется, что, когда вы пытаетесь передать в шаблон О или NULL в каче­стве нулевого указателя, вывод типа для переданного аргумента дает вместо типа указателяцелочисленный тип (обычно int ) .

В результате ни О, ни NULL не может быть передано с по­мощью прямой передачи как нулевой указатель. Решение проблемы простое: передаватьnullptr вместо О и NULL. Детальную информацию вы можете найти в разделе 3.2.Целочи с лен ные члены-данные s tatic cons tи cons texpr без определени йВ качестве общего правила не требуется определять в классах целочисленные члены­данные stat i c const и constexpr; одних объявлений вполне достаточно. Дело в том, чтокомпиляторы выполняют распространение con s t для значений таких членов, тем самымустраняя необходимость выделять для них память.

Например, рассмотрим такой код:class Widget {puЫ i c :/ / Объявление MinVals :static constexpr std: : size_t МinVals=28;);1 1 Объявления MinVal s нетstd: : vector<int> widgetDa t a ;widgetData . reserve (Widget : : МinVals ) ; / / Использование MinVa ls214Гпава 5. Rvalue-ccыnки, сема н тика перемеще н ий и прямая передачаЗдесь мы используем Widg e t : : M i nVa l s (далее - просто Mi nVa l s ) для указания на­чальной емкости widgetData, даже несмотря на то, что определения M i nVa l s нет.

Ком­пиляторы обходят отсутствующее определение (как и должны это делать) подстановкойзначения 28 во все места, где упоминается MinVa l s . Тот факт, что для значения MinVa l sне выделена память, проблемой н е является. Если берется адрес M i nVa l s (например, кто­то создает указатель на M i nVa l s ) , то M inVa l s требует места в памяти (чтобы указателюбыло на что указывать), и тогда приведенный выше код хотя и будет компилироваться,не будет компоноваться до тех пор, пока не будет предоставлено определение M i nVa l s .С учетом этого представим, что f (которой функция fwd передает аргумент) объявле­на следующим образом:void f ( std: : si ze_t val ) ;Вызов f с M inVa ls проблемы не представляет, поскольку компиляторы просто заменяютMinVa l s его значением:11 ОК, рассматривается как " f ( 2 8 ) "f (Widget : :МinVals) ;Увы, все не так хорошо, если попытаться вызвать f через fwd:fwd (Widget : :МinVals ) ;/ / Ошибка ! Не должно компоноватьсяЭтот код компилируется, но не должен компоноваться.

Если это напоминает вам про­исходящее при взятии адреса MinVa l s, это хорошо, потому что проблема в обоих случаяходна и та же.Хотя нигде в исходном коде не берется адрес MinVa ls, параметром fwd является уни­версальная ссылка, а ссылки в коде, сгенерированном компилятором, обычно рассматри­ваются как указатели. В бинарном коде программы указатели и ссылки, по сути, пред­ставляют собой одно и то же. На этом уровне можно считать, что ссылки - это простоуказатели, которые автоматически разыменовываются.

В таком случае передача MinValsпо ссылке фактически представляет собой то же, что и передача по указателю, а раз так,то должна иметься память, на которую этот указатель указывает. Передача целочислен­ных членов-данных s t a t i c const и constexpr по ссылке в общем случае требует, чтобыони были определены, и это требование может привести к неудачному применению пря­мой передачи там, где эквивалентный код без прямой передачи будет успешен.Возможно, вы обратили внимание на некоторые юркие слова, употребленные мноювыше. Я сказал, что код "не должен" компоноваться.

Характеристики

Тип файла
PDF-файл
Размер
12,67 Mb
Тип материала
Высшее учебное заведение

Список файлов книги

Свежие статьи
Популярно сейчас
Как Вы думаете, сколько людей до Вас делали точно такое же задание? 99% студентов выполняют точно такие же задания, как и их предшественники год назад. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6384
Авторов
на СтудИзбе
308
Средний доход
с одного платного файла
Обучение Подробнее