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

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

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

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

Предположим, чтовам надо вычислить индекс элемента в контейнере с итераторами произвольного досту­па (например, s t d : : vector, s t d : : deque или s t d : : a rray} и вы получаете значение типаdouЬle между О . О и 1 . О, указывающее, насколько далеко от начала контейнера располо­жен этот элемент (О . 5 указывает на середину контейнера). Далее, предположим, что выуверены в том, что полученный индекс можно разместить в int. Если ваш контейнерс, а значение с плавающей точкойd, индекс можно вычислить следующим образом:--int index=d * ( c . s i ze ( )-1) ;Но здесь скрыт тот факт, что вы преднамеренно преобразуете douЫe справа от знака "="в int.

Идиома явно типизированного инициализатора делает этот факт очевидным:auto index=static cast<int> (d * ( c . si ze ( )_-1) ) ;2.2. Если auto выводит нежелательный тип, используйте явно типизированный и н и циализатор59Сnедует запомнить•"Невидимые" прокси-типы могут привести auto к выводу неверного типа инициа­лизирующего выражения.•Идиома явно типизированного инициализатора заставляет auto выводить тот тип,который нужен вам.бОГnава 2. Обьявnение autoГЛАВА 3Перех од к с о в ременном у С++Когда дело доходит до умных терминов, С++ 1 1 и С++ 1 4 есть чем похвастаться.

auto,интеллектуальные указатели, семантика перемещения, лямбда-выражения, паралле­лизм - каждая возможность настолько важна, что я посвящаю ей отдельную главу. Оченьважно освоить все эти возможности, но большой путь к эффективному программирова­нию на современном С++ требует множества маленьких шажков. Каждый шаг отвечаетна конкретные вопросы, возникающие во время путешествия от С++98 к современномуС++.

Когда следует использовать фигурные скобки вместо круглых для создания объек­тов? Почему объявление псевдонимов лучше, чем применение t ypedef? Чем constexprотличается от const? Как связаны константные функции-члены и безопасность с точкизрения потоков? Этот список можно продолжать и продолжать. В этой главе постепенно,один за другим, даются ответы на эти вопросы.3.1 .

Разпичие между { } и ( ) при создании объектовВ зависимости от вашей точки зрения выбор синтаксиса для инициализации объек­тов в С++ 1 1 либо очень богатый, либо запутанный и беспорядочный. Как правило, ини­циализирующие значения указываются с помощью круглых скобок, знака равенства илифигурных скобок:11 Инициализатор в круглых скобкахint х ( О ) ;int у = О ; // Инициализатор после " = "int z { О } ; // Инициализатор в фигурных скобкахВо многих случаях можно использовать знак равенства и фигурные скобки одновременно:intz = { О } ; // Инициализатор использует "=" и фигурные скобкиВ оставшейся части данного раздела я в основном буду игнорировать синтаксис, в ко­тором одновременно используются знак равенства и фигурные скобки, поскольку С++обычно трактует его так же, как и версию только с фигурными скобками.Сторонники "полного беспорядка" указывают на то, что применение знака равенствадля инициализации часто сбивает с толку новичков в С++, которые считают, что имеютдело с присваиванием, хотя на самом деле это не так.

Для встроенных типов наподобиеi nt эта разница носит чисто академический характер, но в случае пользовательских ти­пов очень важно отличать инициализацию от присваивания, поскольку при этом вызы­ваются различные функции:Widget wl ;Widget w2wlw2 ;=/ / Вызов конструктора по умолчаниюwl ; / / Не присваивание, а копирующий конструктор/ / Присваивание ; вызов оператора operator= ( )Даже при наличии нескольких синтаксисов инициализации существовали определенныеситуации, когда в С++98 не было возможности выразить желаемую инициализацию. На­пример, было невозможно прямо указать, что контейнер STL должен быть создан содер­жащим определенный набор значений (например, 1 , 3 и 5).Для устранения путаницы из-за нескольких синтаксисов инициализации и решенияпроблемы охвата всех сценариев инициализации С++ 1 1 вводит унифицированную иници­ализацию (uпiform initializatioп): единый синтаксис инициализации, который может, какминимум концептуально, использоваться везде и выражать все.

Он основан на фигурныхскобках, и по этой причине я лично предпочитаю термин "фигурная инициализация"(braced initialization). Унифицированная инициализация - это идея. Фигурная инициа­лизация - это синтаксическая конструкция.Фигурная инициализация позволяет выразить то, что было невозможно выразить ра­нее.

С помощью фигурных скобок легко указать начальное содержимое контейнера:std: : vector<int> v{ 1 , 3, 5 } ; // v иэначально содержит 1 , 3, 5Фигурные скобки могут также использоваться для указания значений инициализациипо умолчанию для нестатических членов-данных. Эта возможность - новая в С++ 1 1 может использоваться с синтаксисом "=': но не с круглыми скобками:class Widgetprivate :int х { О } ; / / ОК, эначение х по умолчанию равно Оint у = О ; 1 1 Тоже ОК/ / Ошибка !int z ( O) ;};С другой стороны, некопируемые объекты (например, s t d : : a tomi cсм.

раздел 7.6)могут быть инициализированы с помощью фигурных или круглых скобок, но не с по­мощью знака равенства:-std : : atomic<int> ai l { О } ; // ОК/ / ОКstd : : atomic<int> ai2 ( 0 ) ;std: : atomic< int> a i 3 = О ; 1 1 Ошибка !Легко понять, почему фигурная инициализация названа "унифицированной''. Из трехспособов обозначения выражений инициализации только фигурные скобки могут ис­пользоваться везде.62Гnава 3 . Переход к современному ( ++Новая возможность фигурной инициализации заключается в том, что она запрещаетнеявные сужающие преобразования среди встроенных типов. Если значение выраженияв фигурном инициализаторе не может быть гарантированно выражено типом инициали­зируемого объекта, код не компилируется:douЫeх,int suml {у, z ;х+у + z } ; / / Ошибка ! Сумма douЫe может/ / не выражаться с помощью intИнициализация с использованием круглых скобок и знака равенства не выполняет про­верку сужающего преобразования, поскольку это может привести к неработоспособнос­ти большого количества старого кода:int sum2 ( x+y+ z ) ; // ОК ( значение выражения усекается до int )iпt sumЗ = x+y+ z ; / /Обращает на себя внимание еще одна особенность фигурной инициализации - онане подвержена наиболее неприятному анализу в С++.

Побочным эффектом правила С++,согласно которому все, что в ходе синтаксического анализа может рассматриваться какобъявление, должно рассматриваться как таковое, является так называемый наиболее не­приятный анализ, который чаще всего досаждает разработчикам, когда они хотят создатьобъект по умолчанию, а в результате получают объявление функции. Корень проблемыкроется в том, что если вы хотите вызвать конструктор с аргументом, вы делаете это при­мерно следующим образом:Widget wl (lO) ; // Вызов конструктора Widget с аргументом10Но если в ы пытаетесь вызвать конструктор Widget без аргументов с помощью аналогич­ного синтаксиса, то фактически объявляете функцию вместо объекта:Widget w2 ( ) ; / / Синтаксический анализ рассматривает зто как11 объявление функции w2 , возвращающей Widget 1Функции не могут быть объявлены с использованием фигурных скобок для списка пара­метров, так что конструирование объекта по умолчанию с применением фигурных ско­бок такой проблемы не вызовет:Widget wЗ { ) ; / / Вызов конструктора Widget без аргументовТаким образом, в пользу фигурной инициализации имеется много "за".

Это синтаксис,который может использоваться в самых разнообразных контекстах, предотвращающийнеявные сужающие преобразования и не подверженный неприятностям с синтаксиче­ским анализом С++. Тройное "за"! Так почему бы не озаглавить раздел просто "Исполь­зуйте синтаксис фигурной инициализации"?Основной недостаток фигурной инициализации - временами сопровождающее ееудивительное поведение. Такое поведение вырастает из необыкновенно запутанных вза­имоотношений между фигурной инициализацией, st d : : i n i t i al i zer_ l i s t и разрешени­ем перегрузки конструкторов. Их взаимодействие может привести к коду, который, как3.1 . Различие между {} и () при создании объектов63кажется, должен делать что-то одно, а в результате делает что-то совсем другое.

Напри­мер, в разделе 1 .2 поясняется, что когда переменная, объявленная как auto, имеет ини­циализатор в фигурных скобках, то выводимым типом является std : : i n i t i a l i z e r_l i st,несмотря на то что другой способ объявления переменной с тем же инициализаторомдаст более ожидаемый тип. В результате чем больше вам нравится auto, тем меньше эн­тузиазма вы должны проявить по отношению к фигурной инициализации.В вызовах конструктора круглые и фигурные скобки имеют один и тот же смысл, покав конструкторах не принимают участие параметры std : : ini t i a l i zer_ l i s t :class Widget {puЫ i c :Widget ( int i , bool Ь ) ;/ / Конструкторы н е имеют параметровWidget (int i , douЫe d ) ; // std : : initiali zer l i st};WidgetWidgetWidgetWidgettrue) ; 1 1 Вызовtrue } ; 1 1 Вызов1 1 Вызовw3 ( 1 0 , 5 .

0 ) ;11 Вызовw4 { 1 0 , 5 . 0 } ;wl ( l O ,w2 { 1 0 ,первогопервоговтороговторогоконструктораконструктораконструктораконструктораЕсли же одини л и несколько конструкторов объявляют параметр типавызовы, использующие синтаксис фигурной инициализации,строго предпочитают перегрузки, принимающие s t d : : init i a l i zer_l i s t . Строго. Еслиу компилятора есть лю бой спосо б истолковать вызов с фигурным инициализатором какконструктор, принимающий s t d : : i n i t i a l i ze r_ l i s t , он использует именно это толко­вание. Если класс W i dg e t выше дополнить конструктором, принимающим, например,std : : i n i t i a l i ze r l i s t ,_s td : : i n i t i a l i ze r l i st < l ong douЫe>_class Widget (puЫ i c :Widget ( int i , bool Ь ) ;Widget ( int i , douЫe d ) ;11 Как и ранее11 Как и ранееWidget (std: : initializer list<long douЫe> il) ; // Добавлен_};то w2 и w4 будут созданы с помощью нового конструктора, несмотря на то что типэлементов s t d : : i п i t i a l i z e r l i s t (в данном случаеlong douЫe ) хуже соот­ветствует обоим аргументам по сравнению с конструкторами, не принимающимиst d : : ini t i a l i ze r l is t ! Смотрите сами:_-Widget wl ( l O , true) ; / / Использует круглые скобки и, как и11 ранее, вызывает первый конструкторWidget w2 { 1 0 , true } ; / / Использует фигурные скобки, но теперь64Глава 3 .

Переход к современному С++1 1 вызывает третий конструктор11 (10 иtrue преобразуются в long douЬle )Widget wЗ ( 1 0 , 5 . О) ;1 1 Использует круглые скобки и, как иWidget w4 { 1 0 , 5 . 0 } ;1 1 Использует фигурные скобки , НО теперь1 1 ранее, вьGывает второй конструктор1 1 вызывает третий конструктор11 (10 и5 . 0 преобразуются в long douЬl e )Даже то, что в обычной ситуации представляет собой копирующий или перемещающийконструктор, может быть перехвачено конструктором с s td : : i n i t i а l i zer_l i s t :class Widget {puЬli c :Widget ( int i , bool Ь ) ;/ / Как ранееWidget ( int i , douЫe d) ;/ / Как ранееWidget ( s td : : init ializer_list<long douЬle> i l ) ; / / Как ранееoperator float ( ) const;1 1 Преобразование воfloat};Widget w5 (w4 ) ;1 1 Использует круглые скобки , вызывает1 1 копирукщий конструкторWidget wб{w4 } ;1 1 Использует фигурные скобки, вызов1 1 конструктора сs td : : initiali zer_list( w4 преобразуется в о floa t , а float1 1 преобразуется в long douЬle )11Widget w7 ( std : : move (w4 ) ) ; 1 1 Использует круглые скобки, вызывает1 1 перемещающий конструкторWidget w8 { std: : move (w4 ) } ; 1 1 Использует фигурные скобки, ВЬGОВ1 1 конструктора с std : : initiali zer_l ist1 1 ( все, как для w б )Определение компилятором соответствия фигурных и нициализаторов конструкто­рам с std : : i п i t i a l i z e r_ l i s t настолько строгое, что доминирует даже тогда, когда кон­структор с s t d : : in i t i a l i ze r_l i s t с наилучшим соответствием не может быть вызван,например:class WidgetpuЬli c :Widget ( int i , bool Ь ) ;/ / Как ранееWidget ( int i , douЬle d) ; / / Как ранееWidget ( std : : initiali zer_l ist<Ьool > i l ) ; / / Теперь тип1 1 элемента-bool/ / Нет функций неявного преобразованияWidget w{lO , 5 .

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

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

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

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