С. Мейерс - Эффективный и современный C++ (1114942), страница 4
Текст из файла (страница 4)
(Более узкое определение происходит из С++98, более широкое - из C++ll.) Дальнейшее обобщение путем добавления указателей на функциичлены дает то, что известно как вызываемый объект (callaЫe object). Вообще говоря,-18В ведениеможно иrнорировать эти тонкие отличия и просто рассматривать функциональные и вызываемые объекты как сущности в С++, которые моrут быть вызваны с помощью некоторой разновидности синтаксиса вызова функции.Функциональные объекты, создаваемые с помощью лямбда-выражений, известны какзамь1кания (closures). Различать лямбда-выражения и замыкания, ими создаваемые, приходится редко, так что я зачастую rоворю о них обоих как о лямбдах (lambda).
Точно также я редко различаю шаблоны функций (fuпction templates) (т.е. шаблоны, которые rенерируют функции) и шаблонные функции (template ftшctions) (т.е. функции, сrенерированные из шаблонов функций). То же самое относится к шаблонам классов и шаблоннымклассам.Мноrие сущности в С++ моrут быть как объявлены, так и определены. Объявлениявводят имена и типы, не детализируя информацию о них, такую как их местоположениев памяти или реализация:extern intх;class Widget ;11 Объявление объекта11 Объявление класс аbool func ( const Widget& W); 11 Объявление функцииenшn class Color;11 Объявление перечисления11 с областью видимости11 ( см.
раздел 3.4)Определение предоставляет информацию о расположении в памяти и деталях реализации:intх;cla ss Widget)11 Определение объекта11 Определение класса;bool func ( const Widget& w){ return w . size ( ) < 1 0 ; 1 // Определение функцииenurn class Color{ Yellow, Red, Blue f ;11 Определение перечисленияОпределение можно квалифицировать и как объявление, так что, если только то, чтонечто представляет собой определение, не является действительно важным, я предпочитаю использовать термин "объявление·:Сигнатуру функции я определяю как часть ее объявления, определяющую типыпараметров и возвращаемый тип. Имена функции и параметров значения не имеют.
В приведенном выше примере сиrнатура функции func представляет собойbool (const Widget&) . Исключаются элементы объявления функции, отличные от типов ее параметров и возвращаемоrо типа (например. noexcept или constexpr, еслитаковые имеются). (Модификаторы noexcept и constexpr описаны в разделах 3.8В ведение19и 3.9.) Официальное определение термина "сигнатура" несколько отличается от моего,но в данной книге мое определение оказывается более полезным.
(Официальное определение иногда опускает возвращаемый тип.)Новый стандарт С++ в общем случае сохраняет корректность кода, написанного для более старого стандарта, но иногда Комитет по стандартизации не рекомендует применять теили иные возможности. Такие возможности находятся в "камере смертников" стандартизации и могут быть убраны из новых версий стандарта.
Компиляторы могут предупреждатьоб использовании программистом таких устаревших возможностей (но могут и не делатьэтого), но в любом случае их следует избегать. Они могут не только привести в будущемк головной боли при переносе, но и в общем случае они ниже по качеству, чем возможности, заменившие их. Например, st d : : a ut o _pt r не рекомендуется к применениюв C++ l l , поскольку std:: unique_pt r выполняет ту же работу, но лучше.Иногда стандарт гласит, что результатом операции является неопределенное поведение (undefined behavior).
Это означает, что поведение времени выполнения непредсказуемо, и от такой непредсказуемости, само собой разумеется, следует держаться подальше.Примеры действий с неопределенным поведением включают использование квадратныхскобок ( []) для индексации за границами std: :vec t o r, разыменование неинициализированного итератора или гонку данных (т.е. когда два или более потоков, как минимумодин из которых выполняет запись, одновременно обращаются к одному и тому же месту в памяти).Я называю встроенный указатель, такой как возвращаемый оператором new, обычнымуказателем (raw pointer). Противоположностью обычному указателю является интеллектуальный указатель (smart pointer).
Интеллектуальные указатели обычно перегружаютоператоры разыменования указателей (oper a t o r-> и opera t o r*), хотя в разделе 4.3поясняется, что интеллектуальный указатель std::weak_ptr является исключением.Зам е ча н ия и пр едл ож ен ияЯ сделал все возможное, чтобы книга содержала только ясную, точную, полезную информацию, но наверняка есть способы сделать ее еще лучшей.
Если вы найдете в книге ошибки любого рода (технические, разъяснительные, грамматические, типографскиеи т.д.) или если у вас есть предложения о том, как можно улучшить книгу, пожалуйста,напишите мне по адресу ernc++@a r i st e i a . сот. В новых изданиях книги ваши замечания и предложения обязательно будут учтены.Список исправлений обнаруженных ошибок можно найти по адресу ht tp://www.a rist eia.corn/BookErra t a /ernc++-erra t a .htrnl.О т р едакцииРедакция выражает признательность профессору университета Иннополис Е. Зуеву заобсуждения и советы при работе над переводом данной книги.20В ведениеЖде м ва ши х отзывов!Вы, читатель этой книги, и есть главный ее критик. Мы ценим ваше мнение и хотимзнать, что было сделано нами правильно, что можно было сделать лучше и что еще выхотели бы увидеть изданным нами.
Нам интересны любые ваши замечания в наш адрес.Мы ждем ваших комментариев и надеемся на них. Вы можете прислать нам бумажноеили электронное письмо либо просто посетить наш веб-сайт и оставить свои замечаниятам. Одним словом, любым удобным для вас способом дайте нам знать, нравится ли вамэта книга, а также выскажите свое мнение о том, как сделать наши книги более интересными для вас.Отправляя письмо или сообщение, не забудьте указать название книги и ее авторов,а также свой обратный адрес. Мы внимательно ознакомимся с вашим мнением и обязательно учтем его при отборе и подготовке к изданию новых книг.Наши электронные адреса:E-mail:WWW:i nfo@wi ll i amspuЫ i sh i ng.comhtt p://www .
wi ll i ams puЫ i s h i ng . comНаши почтовые адреса:в России: 1 27055, Москва, ул. Лесная, д. 43, стр. 1в Украине: 03 1 50, Киев, а/я 1 52Введение21ГЛАВА 1Выв од т и п о вВ С++98 имеется единственный набор правил вывода типов - для шаблонов функций. С++ 1 1 немного изменяет этот набор правил и добавляет два новых - для auto и дляdecltype. С++ 14 расширяет контексты использования ключевых слов auto и decltype.Все более широкое применение вывода типов освобождает вас от необходимости правильной записи очевидных или излишних типов.
Он делает программы на С++ болеелегко адаптируемыми, поскольку изменение типа в одной точке исходного текста автоматически распространяется с помощью вывода типов на другие точки. Однако он можетсделать код более сложным для восприятия, так как выводимые компилятором типы могут не быть настолько очевидными, как вам бы хотелось.Без ясного понимания того, как работает вывод типов, эффективное программирование на современном С++ невозможно. Просто есть слишком много контекстов, в которых имеет место вывод типа: в вызовах шаблонов функций, в большинстве ситуаций,в которых встречается ключевое слово aut o, в выражениях decltype и, начиная с С++ 14,там, где применяется загадочная конструкция decltype (auto).Эта глава содержит информацию о выводе типов, которая требуется каждому разработчику на языке программирования С++.
Здесь поясняется, как работает вывод типашаблона, как строится auto и как проходит свой путь decltype. Здесь даже объясняется,как заставить компилятор сделать видимыми результаты своего вывода типа, чтобы убедиться, что компилятор выводит именно тот тип, который вы хотели.1.1 . Вывод типа шаблонаКогда пользователи сложной системы не знают, как она работает, но их устраивает то,что она делает, это говорит об удачном проектировании системы. Если мерить такой мерой, то вывод типа шаблона в С++ является огромным успехом. Миллионы программистов передают аргументы шаблонным функциям с вполне удовлетворительными результатами несмотря на то, что многие из этих программистов не способны на большее, чемочень приближенное и расплывчатое описание того, как же были выведены эти типы.Если вы относитесь к числу этих программистов, у меня для вас две новости - хорошая и плохая.
Хорошая новость заключается в том, что вывод типов для шаблонов является основой для одной из наиболее привлекательных возможностей современного С++:auto. Если вас устраивало, как С++98 выводит типы для шаблонов, вас устроит и то, какС++ 1 1 выводит типы для auto. Плохая новость заключается в том, что когда правилавывода типа шаблона применяются в контексте auto, они оказываются немного менееинтуитивными, чем в приложении к шаблонам. По этой причине важно действительнопонимать аспекты вывода типов шаблонов, на которых построен вывод типов для auto.Этот раздел содержит информацию, которую вы должны знать.Если вы готовы посмотреть сквозь пальцы на применение небольшого количествапсевдокода, то можно рассматривать шаблон функции как имеющий следующий вид:template<typename Т>void f(Param7YPE1 param) ;Вызов может выглядеть следующим образом:f (expr);11 Вызов fснекоторым выражениемВ процессе компиляции компилятор использует expr для вывода двух типов: типаи типа ParamT ype.
Эти типы зачастую различны, поскольку Pa ramType часто содержит "украшения", например const или квалификаторы ссылки. Например, если шаблонобъявлен какТternplate<typename Т>void f(const Т& param) ;//ParamType-const Т&и мы осуществляем вызовintхО;f (х);11 Вызов f с параметром intто Т выводится как int, а ParamTypeкак const i n t & .Вполне естественно ожидать, что тип, выведенный для Т , тот же, что и тип переданного функции аргумента, т.е. что Тэто тип выражения expr. В приведенном выше примере это так: х значение типа int и Т выводится как int. Но вывод не всегда работаеттаким образом.
Тип, выведенный для т, зависит не только от типа expr, но и от видаPa ramType. Существует три случая.---•ParamType представляет собой указатель или ссылку, но не универсальную ссылку.(Универсальные ссылки рассматриваются в разделе 5.2. Пока что все, что вам надознать, - что они существуют и не являются ни ссылками lvalue, ни ссылками rvalue.)•ParamType является универсальной ссылкой.•Pa ramType не является ни указателем, ни ссылкой.Следовательно, нам надо рассмотреть три сценария вывода.