Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 - [92]
. В этом случае код не компилируется.
• Компиляторы выводят “неверный” тип одного или нескольких параметров >fwd
. Здесь “неверный” может означать как то, что инстанцирование >fwd
не компилируется с выведенными типами, так и то, что вызов >f
с использованием выведенных типов >fwd
ведет себя не так, как непосредственный вызов >f
с аргументами, переданными в >fwd
. Одним источником такого отклонения в поведении могла бы быть ситуация, когда у >f
имеется перегрузка, и из-за “некорректного” вывода типов эта перегрузка >f
, вызываемая в >fwd
, отличалась бы от перегруженной функции >f
, используемой при непосредственном вызове.
В приведенном выше вызове “>fwd({1,2,3})
” проблема заключается в том, что передача инициализатора в фигурных скобках параметру шаблона функции, не объявленному как >std::initializer_list
, заставляет его быть, как предписывает стандарт, “не выводимым контекстом”. На простом человеческом языке это означает, что компиляторам запрещено выводить тип для выражения >{1,2,3}
в вызове >fwd
, поскольку параметр >fwd
не объявлен как >std::initializer_list
. Не имея возможности вывести тип параметра >fwd
, компиляторы, понятно, вынуждены отклонять такой вызов.
Интересно, что в разделе 1.2 поясняется, что вывод типа для переменных >auto
, инициализированных с помощью инициализатора в фигурных скобках, успешен. Такие переменные считаются объектами типа >std::initializer_list
, и это обеспечивает простой обходной путь для случаев, когда тип передающей функции должен быть выведен как >std::initializer_list
: объявить локальную переменную как auto, а затем передать ее в передающую функцию:
>auto il = { 1, 2, 3 }; // Тип il выводится как
> // std::initializer_list
>fwd(il); // OK, прямая передача il в f
>0
и >NULL
в качестве нулевых указателейВ разделе 3.2 поясняется, что, когда вы пытаетесь передать в шаблон >0
или >NULL
в качестве нулевого указателя, вывод типа для переданного аргумента дает вместо типа указателя целочисленный тип (обычно >int
). В результате ни >0
, ни >NULL
не может быть передано с помощью прямой передачи как нулевой указатель. Решение проблемы простое: передавать >nullptr
вместо >0
и >NULL
. Детальную информацию вы можете найти в разделе 3.2.
>static const
и >constexpr
без определенийВ качестве общего правила не требуется определять в классах целочисленные члены-данные >static const
и >constexpr
; одних объявлений вполне достаточно. Дело в том, что компиляторы выполняют распространение >const
для значений таких членов, тем самым устраняя необходимость выделять для них память. Например, рассмотрим такой код:
>class Widget {
>public:
> // Объявление MinVals:
> static constexpr std::size_t MinVals = 28;
>};
>… // Определения MinVals нет
>std::vector
>widgetData.reserve(Widget::MinVals); // Использование MinVals
Здесь мы используем >Widget::MinVals
(далее — просто >MinVals
) для указания начальной емкости >widgetData
, даже несмотря на то, что определения >MinVals
нет. Компиляторы обходят отсутствующее определение (как и должны это делать) подстановкой значения 28 во все места, где упоминается >MinVals
. Тот факт, что для значения >MinVals
не выделена память, проблемой не является. Если берется адрес >MinVals
(например, кто-то создает указатель на >MinVals
), то >MinVals
требует места в памяти (чтобы указателю было на что указывать), и тогда приведенный выше код хотя и будет компилироваться, не будет компоноваться до тех пор, пока не будет предоставлено определение >MinVals
.
С учетом этого представим, что >f
(которой функция >fwd
передает аргумент) объявлена следующим образом:
>void f(std::size_t val);
Вызов >f
с >MinVals
проблемы не представляет, поскольку компиляторы просто заменяют >MinVals
его значением:
>f(Widget::MinVals); // OK, рассматривается как "f(28)"
Увы, все не так хорошо, если попытаться вызвать >f
через >fwd
:
>fwd(Widget::MinVals); // Ошибка! Не должно компоноваться
Этот код компилируется, но не должен компоноваться. Если это напоминает вам происходящее при взятии адреса >MinVals
, это хорошо, потому что проблема в обоих случаях одна и та же.
Хотя нигде в исходном коде не берется адрес >MinVals
, параметром >fwd
является универсальная ссылка, а ссылки в коде, сгенерированном компилятором, обычно рассматриваются как указатели. В бинарном коде программы указатели и ссылки, по сути, представляют собой одно и то же. На этом уровне можно считать, что ссылки — это просто указатели, которые автоматически разыменовываются. В таком случае передача >MinVals
по ссылке фактически представляет собой то же, что и передача по указателю, а раз так, то должна иметься память, на которую этот указатель указывает. Передача целочисленных членов-данных >static const
и >constexpr
по ссылке в общем случае требует, чтобы они были определены, и это требование может привести к неудачному применению прямой передачи там, где эквивалентный код без прямой передачи будет успешен.
Возможно, вы обратили внимание на некоторые юркие слова, употребленные мною выше. Я сказал, что код “не должен” компоноваться. Ссылки “обычно” рассматриваются как указатели. Передача целочисленных членов-данных
В этой книге известный автор Скотт Мейерс раскрывает секреты настоящих мастеров, позволяющие добиться максимальной эффективности при работе с библиотекой STL.Во многих книгах описываются возможности STL, но только в этой рассказано о том, как работать с этой библиотекой. Каждый из 50 советов книги подкреплен анализом и убедительными примерами, поэтому читатель не только узнает, как решать ту или иную задачу, но и когда следует выбирать то или иное решение — и почему именно такое.
Когда приходится инкапсулировать, то иногда лучше меньше, чем большеЯ начну со следующего утверждения: Если вы пишете функцию, которая может быть выполнена или как метод класса, или быть внешней по отношению к классу, Вы должны предпочесть ее реализацию без использования метода. Такое решение увеличивает инкапсуляцию класса. Когда Вы думаете об использовании инкапсуляции, Вы должны думать том, чтобы не использовать методы.Удивлены? Читайте дальше.
Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.
Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.