Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.93/15: Рейтинг темы: голосов - 15, средняя оценка - 4.93
2723 / 1887 / 559
Регистрация: 05.06.2014
Сообщений: 5,499
1

Лямбды и захват переменных

29.10.2015, 15:54. Показов 3043. Ответов 10
Метки нет (Все метки)

Лямбды могут захватывать переменные через [value1,value2]{}. Вопрос: а куда, собственно, эти переменные захватываются - в статический буфер общий для всех вызовов лямбды или в локальный буфер формируемый под каждый вызов и передающийся лямбде на манер this?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
29.10.2015, 15:54
Ответы с готовыми решениями:

Захват const переменной из лямбды: разный результат в g++ и clang
Добрый день. #include <iostream> template <class T> void foo(const T& t) { const int a =...

Лямбды
Непонятно, как работает это простенький код, и почему именно так: int id = 0; auto f = ()...

лямбды
Необходимо определить функции так, чтобы проходили доктесты. Используй лямбды, а не вложенные...

Лямбды и делегаты
есть код using System; namespace ConsoleApp1 { public delegate void MyDelegate(); ...

10
:)
Эксперт С++
4769 / 3263 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
29.10.2015, 16:01 2
Лямбда это по сути сахар для создания функтора, поэтому логично предположить, что это будут некие данные-члены автоматически сгенеренного объекта функтора.
0
6992 / 6030 / 2738
Регистрация: 14.04.2014
Сообщений: 25,792
29.10.2015, 16:01 3
Там же есть указатели - по ссылке или по значению брать (= и &).
0
2723 / 1887 / 559
Регистрация: 05.06.2014
Сообщений: 5,499
29.10.2015, 16:15  [ТС] 4
Цитата Сообщение от Tulosba Посмотреть сообщение
Лямбда это по сути сахар для создания функтора, поэтому логично предположить, что это будут некие данные-члены автоматически сгенеренного объекта функтора.
Проблема в том, что std::function ничего про эти захваченные переменные не знает, а значит данных-членов под захват там нет. Вот я и не пойму куда же тогда эти захваченные переменные деваются.
Цитата Сообщение от nmcf Посмотреть сообщение
Там же есть указатели - по ссылке или по значению брать (= и &).
Ссылка тоже требует памяти под свое хранение. Если, конечно, адрес объекта на который ведет ссылка не известен на стадии компиляции (а он известен только для static переменных).
0
:)
Эксперт С++
4769 / 3263 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
29.10.2015, 16:28 5
Пример для иллюстрации:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
 
void print(int i) {
    std::cout << i << std::endl;
}
 
struct F {
    F(int i): i_(i) {}
    void operator()() const { print(i_); }
private:
    int i_;
};
 
int main() {
    
    int v = 42;
 
    auto l = [v]{ print(v); };
    l();
    
    auto f = F(v);
    f();
}
По сути, l есть альтернативный способ достичь того же, что делает f.

Т.е. при захвате по значение у тебя будет сгенерирован член-данных с типом значения, при захвате по ссылке - член-данных с типом ссылки.
0
2723 / 1887 / 559
Регистрация: 05.06.2014
Сообщений: 5,499
29.10.2015, 16:31  [ТС] 6
Цитата Сообщение от Tulosba Посмотреть сообщение
Т.е. при захвате по значение у тебя будет сгенерирован член-данных с типом значения, при захвате по ссылке - член-данных с типом ссылки.
Ок, скажем по другому. Откуда в этом примере std::function<void()> знает что надо сформировать член данных с ссылкой?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include<iostream>
#include<functional>
using namespace std;
int main()
{
    int x=0;
    //в объявлении test ни слова о необходимости хранить ссылку на x
    std::function<void()>test=[&x]{x+=1;};
    //и тем не менее, эта строчка увеличит x на единицу
    test();
    std::cout<<x;
    return 0;
}
0
:)
Эксперт С++
4769 / 3263 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
29.10.2015, 16:39 7
Ровно оттуда же, откуда и при явном использовании функтора:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<iostream>
#include<functional>
using namespace std;
 
struct F {
    F(int& i): i_(i) {}
    void operator()() const { i_+=1; }
private:
    int& i_;
};
 
int main()
{
    int x=0;
    //в объявлении test ни слова о необходимости хранить ссылку на x
    //std::function<void()>test=[&x]{x+=1;};
    F test(x);
    //и тем не менее, эта строчка увеличит x на единицу
    test();
    std::cout<<x;
    return 0;
}
Или теперь мы уже про std::function, а не про лямбду?
1
В астрале
Эксперт С++
8035 / 4792 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
29.10.2015, 17:27 8
Renji, std::function такой объект.
http://en.cppreference.com/w/c... n/function
Принимает любой callable тип и просто хранит его объект.
1
2723 / 1887 / 559
Регистрация: 05.06.2014
Сообщений: 5,499
29.10.2015, 17:30  [ТС] 9
Цитата Сообщение от Tulosba Посмотреть сообщение
Или теперь мы уже про std::function, а не про лямбду?
Мне казалось что раз std::function может быть инициализирован обычной функций, он является просто оберткой вокруг указателя на функцию. А раз он кушает еще и лямбды, значит лямбде должно хватать этого указателя. Посмотрел на sizeof от std::function - понял что ошибся, оно сильно тяжелее указателя.
0
25 / 25 / 11
Регистрация: 07.12.2012
Сообщений: 169
29.10.2015, 18:07 10
Renji, std:function может хранить как функцию так и функциональный объект с одинаковой сигнатурой. А лямбда - это безымянный функциональный объект (функтор).
0
Эксперт С++
8434 / 4105 / 896
Регистрация: 15.11.2014
Сообщений: 9,220
29.10.2015, 20:53 11
Цитата Сообщение от Renji Посмотреть сообщение
Лямбды могут захватывать переменные через [value1,value2]{}. Вопрос: а куда, собственно, эти переменные захватываются - в статический буфер общий для всех вызовов лямбды или в локальный буфер формируемый под каждый вызов и передающийся лямбде на манер this?
лямбда - это обычный класс-функтор.
если лямбда хапанула контекст,
то компилятор сгенерирует функтор с данными-членами.
которые и будут хранить этот контекст.

итого:
никакой разницы между лямбдой,
и как если бы вы сами вручную этот функтор приготовили.

просто удобнее.

Цитата Сообщение от Renji Посмотреть сообщение
Проблема в том, что std::function ничего про эти захваченные переменные не знает
std::function - это всего лишь тонкая обертка над функторами.
ей без разницы на что нацеливаться.
главное, что бы оно могло вызваться согласно протоколу
(типу функции указанному в параметре шаблона)

поэтому, она не заморачивается тем, что под капотом функтора.
просто дергает его оператор()
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.10.2015, 20:53

Не компилится из-за лямбды
void Chair::wait_invite(const int &amp;id_client) { unique_lock &lt;mutex&gt; lk(mx_chair); ...

Лямбды и их применение
Здравствуйте, такой вопрос. Влияет ли на производительность приложения если описывать событие не в...

Лямбды с константами
Всем привет! У меня вопрос: надо создать несколько функций-констант с разными значениями для...

Записать без лямбды
Здравствуйте. Есть изменения значения текстового поля из другого потока через делегат: ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.