Главная » Просмотр файлов » B. Stroustrup - The C++ Programming Language

B. Stroustrup - The C++ Programming Language (794319), страница 66

Файл №794319 B. Stroustrup - The C++ Programming Language (B. Stroustrup - The C++ Programming Language) 66 страницаB. Stroustrup - The C++ Programming Language (794319) страница 662019-05-09СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

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

However,beware that zero elements can be a special case. If so, that case should be handled by a default constructor (§17.3.3).The type of a {}-list can be deduced (only) if all elements are of the same type. For example:auto x0 = {};auto x1 = {1};auto x2 = {1,2};auto x3 = {1,2,3};auto x4 = {1,2.0};// error (no element type)// initializer_list<int>// initializer_list<int>// initializer_list<int>// error : nonhomogeneous listUnfortunately, we do not deduce the type of an unqualified list for a plain template argument.

Forexample:template<typename T>void f(T);f({});f({1});f({1,2});f({1,2,3});// error: type of initializer is unknown// error: an unqualified list does not match ‘‘plain T’’// error: an unqualified list does not match ‘‘plain T’’// error: an unqualified list does not match ‘‘plain T’’I say ‘‘unfortunately’’ because this is a language restriction, rather than a fundamental rule.

Itwould be technically possible to deduce the type of those {}-lists as initializer_list<int>, just like wedo for auto initializers.Similarly, we do not deduce the element type of a container represented as a template. Forexample:template<class T>void f2(const vector<T>&);f2({1,2,3});f2({"Kona","Sidney"});// error : cannot deduce T// error : cannot deduce T290Select OperationsChapter 11This too is unfortunate, but it is a bit more understandable from a language-technical point of view:nowhere in those calls does it say vector.

To deduce T the compiler would first have to decide thatthe user really wanted a vector and then look into the definition of vector to see if it has a constructor that accepts {1,2,3}. In general, that would require an instantiation of vector (§26.2). It would bepossible to handle that, but it could be costly in compile time, and the opportunities for ambiguitiesand confusion if there were many overloaded versions of f2() are reasons for caution. To call f2(), bemore specific:f2(vector<int>{1,2,3});f2(vector<string>{"Kona","Sidney"});// OK// OK11.4 Lambda ExpressionsA lambda expression, sometimes also referred to as a lambda function or (strictly speaking incorrectly, but colloquially) as a lambda, is a simplified notation for defining and using an anonymousfunction object.

Instead of defining a named class with an operator(), later making an object of thatclass, and finally invoking it, we can use a shorthand. This is particularly useful when we want topass an operation as an argument to an algorithm. In the context of graphical user interfaces (andelsewhere), such operations are often referred to as callbacks. This section focuses on technicalaspects of lambdas; examples and techniques for the use of lambdas can be found elsewhere(§3.4.3, §32.4, §33.5.2).A lambda expression consists of a sequence of parts:• A possibly empty capture list, specifying what names from the definition environment canbe used in the lambda expression’s body, and whether those are copied or accessed by reference.

The capture list is delimited by [] (§11.4.3).• An optional parameter list, specifying what arguments the lambda expression requires. Theparameter list is delimited by () (§11.4.4).• An optional mutable specifier, indicating that the lambda expression’s body may modify thestate of the lambda (i.e., change the lambda’s copies of variables captured by value)(§11.4.3.4).• An optional noexcept specifier.• An optional return type declaration of the form −> type (§11.4.4).• A body, specifying the code to be executed. The body is delimited by {} (§11.4.3).The details of passing arguments, returning results, and specifying the body are those of functionsand are presented in Chapter 12.

The notion of ‘‘capture’’ of local variables is not provided forfunctions. This implies that a lambda can act as a local function even though a function cannot.11.4.1 Implementation ModelLambda expressions can be implemented in a variety of ways, and there are some rather effectiveways of optimizing them. However, I find it useful to understand the semantics of a lambda byconsidering it a shorthand for defining and using a function object.

Consider a relatively simpleexample:Section 11.4.1Implementation Model291void print_modulo(const vector<int>& v, ostream& os, int m)// output v[i] to os if v[i]%m==0{for_each(begin(v),end(v),[&os,m](int x) { if (x%m==0) os << x << '\n'; });}To see what this means, we can define the equivalent function object:class Modulo_print {ostream& os; // members to hold the capture listint m;public:Modulo_print(ostream& s, int mm) :os(s), m(mm) {}void operator()(int x) const{ if (x%m==0) os << x << '\n'; }};// captureThe capture list, [&os,m], becomes two member variables and a constructor to initialize them. The& before os means that we should store a reference, and the absence of a & for m means that weshould store a copy.

This use of & mirrors its use in function argument declarations.The body of the lambda simply becomes the body of the operator()(). Since the lambda doesn’treturn a value, the operator()() is void. By default, operator()() is const, so that the lambda bodydoesn’t modify the captured variables. That’s by far the most common case. Should you want tomodify the state of a lambda from its body, the lambda can be declared mutable (§11.4.3.4). Thiscorresponds to an operator()() not being declared const.An object of a class generated from a lambda is called a closure object (or simply a closure).We can now write the original function like this:void print_modulo(const vector<int>& v, ostream& os, int m)// output v[i] to os if v[i]%m==0{for_each(begin(v),end(v),Modulo_print{os,m});}If a lambda potentially captures every local variable by reference (using the capture listclosure may be optimized to simply contain a pointer to the enclosing stack frame.[&]),the11.4.2 Alternatives to LambdasThat final version of print_modulo() is actually quite attractive, and naming nontrivial operations isgenerally a good idea.

A separately defined class also leaves more room for comments than does alambda embedded in some argument list.However, many lambdas are small and used only once. For such uses, the realistic equivalentinvolves a local class defined immediately before its (only) use. For example:292Select Operationsvoid print_modulo(const vector<int>& v, ostream& os, int m)// output v[i] to os if v[i]%m==0{class Modulo_print {ostream& os; // members to hold the capture listint m;public:Modulo_print (ostream& s, int mm) :os(s), m(mm) {}void operator()(int x) const{ if (x%m==0) os << x << '\n'; }};Chapter 11// capturefor_each(begin(v),end(v),Modulo_print{os,m});}Compared to that, the version using the lambda is a clear winner. If we really want a name, we canjust name the lambda:void print_modulo(const vector<int>& v, ostream& os, int m)// output v[i] to os if v[i]%m==0{auto Modulo_print = [&os,m] (int x) { if (x%m==0) os << x << '\n'; };for_each(begin(v),end(v),Modulo_print);}Naming the lambda is often a good idea.

Doing so forces us to consider the design of the operationa bit more carefully. It also simplifies code layout and allows for recursion (§11.4.5).Writing a for-loop is an alternative to using a lambda with a for_each(). Consider:void print_modulo(const vector<int>& v, ostream& os, int m)// output v[i] to os if v[i]%m==0{for (auto x : v)if (x%m==0) os << x << '\n';}Many would find this version much clearer than any of the lambda versions.

However, for_each is arather special algorithm, and vector<int> is a very specific container. Consider generalizingprint_modulo() to handle arbitrary containers:template<class C>void print_modulo(const C& v, ostream& os, int m)// output v[i] to os if v[i]%m==0{for (auto x : v)if (x%m==0) os << x << '\n';}This version works nicely for a map. The C++ range-for-statement specifically caters to the specialcase of traversing a sequence from its beginning to its end. The STL containers make suchSection 11.4.2Alternatives to Lambdas293traversals easy and general. For example, using a for-statement to traverse a map gives a depth-firsttraversal. How would we do a breadth-first traversal? The for-loop version of print_modulo() is notamenable to change, so we have to rewrite it to an algorithm.

For example:template<class C>void print_modulo(const C& v, ostream& os, int m)// output v[i] to os if v[i]%m==0{breadth_first(begin(v),end(v),[&os,m](int x) { if (x%m==0) os << x << '\n'; });}Thus, a lambda can be used as ‘‘the body’’ for a generalized loop/traversal construct represented asan algorithm. Using for_each rather than breadth_first would give depth-first traversal.The performance of a lambda as an argument to a traversal algorithm is equivalent (typicallyidentical) to that of the equivalent loop. I have found that to be quite consistent across implementations and platforms.

The implication is that we have to base our choice between ‘‘algorithm pluslambda’’ and ‘‘for-statement with body’’ on stylistic grounds and on estimates of extensibility andmaintainability.11.4.3 CaptureThe main use of lambdas is for specifying code to be passed as arguments. Lambdas allow that tobe done ‘‘inline’’ without having to name a function (or function object) and use it elsewhere.Some lambdas require no access to their local environment.

Such lambdas are defined with theempty lambda introducer []. For example:void algo(vector<int>& v){sort(v.begin(),v.end());// sor t values// ...sort(v.begin(),v.end(),[](int x, int y) { return abs(x)<abs(y); });// ...}// sor t absolute valuesIf we want to access local names, we have to say so or get an error:void f(vector<int>& v){bool sensitive = true;// ...sort(v.begin(),v.end(),[](int x, int y) { return sensitive ? x<y : abs(x)<abs(y); });}// error : can’t access sensitiveI used the lambda introducer [].

This is the simplest lambda introducer and does not allow thelambda to refer to names in the calling environment. The first character of a lambda expression isalways [. A lambda introducer can take various forms:294Select OperationsChapter 11•[]: an empty capture list. This implies that no local names from the surrounding context canbe used in the lambda body. For such lambda expressions, data is obtained from argumentsor from nonlocal variables.• [&]: implicitly capture by reference. All local names can be used. All local variables areaccessed by reference.• [=]: implicitly capture by value. All local names can be used.

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

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

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

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