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

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

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

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

All names refer to copies ofthe local variables taken at the point of call of the lambda expression.• [capture-list]: explicit capture; the capture-list is the list of names of local variables to becaptured (i.e., stored in the object) by reference or by value. Variables with names precededby & are captured by reference. Other variables are captured by value. A capture list canalso contain this and names followed by ... as elements.• [&, capture-list]: implicitly capture by reference all local variables with names not mentioned in the list. The capture list can contain this.

Listed names cannot be preceded by &.Variables named in the capture list are captured by value.• [=, capture-list]: implicitly capture by value all local variables with names not mentioned inthe list. The capture list cannot contain this. The listed names must be preceded by &. Variables named in the capture list are captured by reference.Note that a local name preceded by & is always captured by reference and a local name not preceded by & is always captured by value. Only capture by reference allows modification of variablesin the calling environment.The capture-list cases are used for fine-grained control over what names from the call environment are used and how. For example:void f(vector<int>& v){bool sensitive = true;// ...sort(v.begin(),v.end()[sensitive](int x, int y) { return sensitive ? x<y : abs(x)<abs(y); });}By mentioning sensitive in the capture list, we make it accessible from within the lambda.

By notspecifying otherwise, we ensure that the capture of sensitive is done ‘‘by value’’; just as for argument passing, passing a copy is the default. Had we wanted to capture sensitive ‘‘by reference,’’ wecould have said so by adding a & before sensitive in the capture list: [&sensitive].The choice between capturing by value and by reference is basically the same as the choice forfunction arguments (§12.2). We use a reference if we need to write to the captured object or if it islarge. However, for lambdas, there is the added concern that a lambda might outlive its caller(§11.4.3.1).

When passing a lambda to another thread, capturing by value ([=]) is typically best:accessing another thread’s stack through a reference or a pointer can be most disruptive (to performance or correctness), and trying to access the stack of a terminated thread can lead to extremelydifficult-to-find errors.If you need to capture a variadic template (§28.6) argument, use .... For example:Section 11.4.3Capture295template<typename... Var>void algo(int s, Var... v){auto helper = [&s,&v...] { return s∗(h1(v...)+h2(v...)); }// ...}Beware that is it easy to get too clever about capture. Often, there is a choice between capture andargument passing.

When that’s the case, capture is usually the least typing but has the greatestpotential for confusion.11.4.3.1 Lambda and LifetimeA lambda might outlive its caller. This can happen if we pass a lambda to a different thread or ifthe callee stores away the lambda for later use. For example:void setup(Menu& m){// ...Point p1, p2, p3;// compute positions of p1, p2, and p3m.add("draw triangle",[&]{ m.draw(p1,p2,p3); });// ...}// probable disasterAssuming that add() is an operation that adds a (name,action) pair to a menu and that the draw()operation makes sense, we are left with a time bomb: the setup() completes and later – maybe minutes later – a user presses the draw triangle button and the lambda tries to access the long-gone localvariables.

A lambda that wrote to a variable caught by reference would be even worse in that situation.If a lambda might outlive its caller, we must make sure that all local information (if any) iscopied into the closure object and that values are returned through the return mechanism (§12.1.4)or through suitable arguments. For the setup() example, that is easily done:m.add("draw triangle",[=]{ m.draw(p1,p2,p3); });Think of the capture list as the initializer list for the closure object andnotation (§11.4.1).[=]and[&]as short-hand11.4.3.2 Namespace NamesWe don’t need to ‘‘capture’’ namespace variables (including global variables) because they arealways accessible (provided they are in scope).

For example:template<typename U, typename V>ostream& operator<<(ostream& os, const pair<U,V>& p){return os << '{' << p.first << ',' << p.second << '}';}296Select OperationsChapter 11void print_all(const map<string,int>& m, const string& label){cout << label << ":\n{\n";for_each(m.begin(),m.end(),[](const pair<string,int>& p) { cout << p << '\n'; });cout << "}\n";}Here, we don’t need to capture cout or the output operator for pair.11.4.3.3 Lambda and thisHow do we access members of a class object from a lambda used in a member function? We caninclude class members in the set of names potentially captured by adding this to the capture list.This is used when we want to use a lambda in the implementation of a member function.

Forexample, we might have a class for building up requests and retrieving results:class Request {function<map<string,string>(const map<string,string>&)> oper;map<string,string> values;// argumentsmap<string,string> results;// targetspublic:Request(const string& s);// parse and store requestvoid execute(){[this]() { results=oper(values); }}// operation// do oper to values yielding results};Members are always captured by reference.

That is, [this] implies that members are accessedthrough this rather than copied into the lambda. Unfortunately, [this] and [=] are incompatible. Thisimplies that incautious use can lead to race conditions in multi-threaded programs (§42.4.6).11.4.3.4 mutable LambdasUsually, we don’t want to modify the state of the function object (the closure), so by default wecan’t.

That is, the operator()() for the generated function object (§11.4.1) is a const member function. In the unlikely event that we want to modify the state (as opposed to modifying the state ofsome variable captured by reference; §11.4.3), we can declare the lambda mutable. For example:void algo(vector<int>& v){int count = v.size();std::generate(v.begin(),v.end(),[count]()mutable{ return −−count; });}The −−count decrements the copy of v’s size stored in the closure.Section 11.4.4Call and Return29711.4.4 Call and ReturnThe rules for passing arguments to a lambda are the same as for a function (§12.2), and so are therules for returning results (§12.1.4).

In fact, with the exception of the rules for capture (§11.4.3)most rules for lambdas are borrowed from the rules for functions and classes. However, two irregularities should be noted:[1] If a lambda expression does not take any arguments, the argument list can be omitted.Thus, the minimal lambda expression is []{}.[2] A lambda expression’s return type can be deduced from its body. Unfortunately, that isnot also done for a function.If a lambda body does not have a return-statement, the lambda’s return type is void.

If a lambdabody consists of just a single return-statement, the lambda’s return type is the type of the return’sexpression. If neither is the case, we have to explicitly supply a return type. For example:void g(double y){[&]{ f(y); }auto z1 = [=](int x){ return x+y; }auto z2 = [=,y]{ if (y) return 1; else return 2; }auto z3 =[y]() { return 1 : 2; }auto z4 = [=,y]()−>int { if (y) return 1; else return 2; }// return type is void// return type is double// error : body too complicated// for return type deduction// return type is int// OK: explicit return type}When the suffix return type notation is used, we cannot omit the argument list.11.4.5 The Type of a LambdaTo allow for optimized versions of lambda expressions, the type of a lambda expression is notdefined.

However, it is defined to be the type of a function object in the style presented in §11.4.1.This type, called the closure type, is unique to the lambda, so no two lambdas have the same type.Had two lambdas had the same type, the template instantiation mechanism might have gotten confused.

A lambda is of a local class type with a constructor and a const member function operator()(). In addition to using a lambda as an argument, we can use it to initialize a variable declaredauto or std::function<R(AL)> where R is the lambda’s return type and AL is its argument list of types(§33.5.3).For example, I might try to write a lambda to reverse the characters in a C-style string:auto rev = [&rev](char∗ b, char∗ e){ if (1<e−b) { swap(∗b,∗−−e); rev(++b,e); } };// errorHowever, that’s not possible because I cannot use an auto variable before its type has been deduced.Instead, I can introduce a name and then use it:void f(string& s1, string& s2){function<void(char∗ b, char∗ e)> rev =[&](char∗ b, char∗ e) { if (1<e−b) { swap(∗b,∗−−e); rev(++b,e); } };298Select OperationsChapter 11rev(&s1[0],&s1[0]+s1.size());rev(&s2[0],&s2[0]+s2.size());}Now, the type of rev is specified before it is used.If we just want to name a lambda, rather than using it recursively, auto can simplify things:void g(vector<string>& vs1, vector<string>& vs2){auto rev = [&](char∗ b, char∗ e) { while (1<e−b) swap(∗b++,∗−−e); };rev(&s1[0],&s1[0]+s1.size());rev(&s2[0],&s2[0]+s2.size());}A lambda that captures nothing can be assigned to a pointer to function of an appropriate type.

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

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

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

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