Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
Renji
1792 / 1210 / 281
Регистрация: 05.06.2014
Сообщений: 3,474
#1

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

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

Лямбды могут захватывать переменные через [value1,value2]{}. Вопрос: а куда, собственно, эти переменные захватываются - в статический буфер общий для всех вызовов лямбды или в локальный буфер формируемый под каждый вызов и передающийся лямбде на манер this?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.10.2015, 15:54     Лямбды и захват переменных
Посмотрите здесь:

Visual C++ Поменять местами значения целых переменных х и у не используя дополнительных переменных
Лямбды C++
C++ Захват const переменной из лямбды: разный результат в g++ и clang
C++ Лямбды в списке инициализации членов
Накладные расходы при создании лямбды C++
C++ Допускается ли такое использование лямбды
Можно ли писать вложенные лямбды? (с++11) C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Tulosba
:)
Эксперт С++
4390 / 3233 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
29.10.2015, 16:01     Лямбды и захват переменных #2
Лямбда это по сути сахар для создания функтора, поэтому логично предположить, что это будут некие данные-члены автоматически сгенеренного объекта функтора.
nmcf
4917 / 4255 / 1425
Регистрация: 14.04.2014
Сообщений: 16,729
29.10.2015, 16:01     Лямбды и захват переменных #3
Там же есть указатели - по ссылке или по значению брать (= и &).
Renji
1792 / 1210 / 281
Регистрация: 05.06.2014
Сообщений: 3,474
29.10.2015, 16:15  [ТС]     Лямбды и захват переменных #4
Цитата Сообщение от Tulosba Посмотреть сообщение
Лямбда это по сути сахар для создания функтора, поэтому логично предположить, что это будут некие данные-члены автоматически сгенеренного объекта функтора.
Проблема в том, что std::function ничего про эти захваченные переменные не знает, а значит данных-членов под захват там нет. Вот я и не пойму куда же тогда эти захваченные переменные деваются.
Цитата Сообщение от nmcf Посмотреть сообщение
Там же есть указатели - по ссылке или по значению брать (= и &).
Ссылка тоже требует памяти под свое хранение. Если, конечно, адрес объекта на который ведет ссылка не известен на стадии компиляции (а он известен только для static переменных).
Tulosba
:)
Эксперт С++
4390 / 3233 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
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.

Т.е. при захвате по значение у тебя будет сгенерирован член-данных с типом значения, при захвате по ссылке - член-данных с типом ссылки.
Renji
1792 / 1210 / 281
Регистрация: 05.06.2014
Сообщений: 3,474
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;
}
Tulosba
:)
Эксперт С++
4390 / 3233 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
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, а не про лямбду?
ForEveR
Модератор
Эксперт С++
7958 / 4720 / 319
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
29.10.2015, 17:27     Лямбды и захват переменных #8
Renji, std::function такой объект.
http://en.cppreference.com/w/cpp/uti...ction/function
Принимает любой callable тип и просто хранит его объект.
Renji
1792 / 1210 / 281
Регистрация: 05.06.2014
Сообщений: 3,474
29.10.2015, 17:30  [ТС]     Лямбды и захват переменных #9
Цитата Сообщение от Tulosba Посмотреть сообщение
Или теперь мы уже про std::function, а не про лямбду?
Мне казалось что раз std::function может быть инициализирован обычной функций, он является просто оберткой вокруг указателя на функцию. А раз он кушает еще и лямбды, значит лямбде должно хватать этого указателя. Посмотрел на sizeof от std::function - понял что ошибся, оно сильно тяжелее указателя.
xEmpire
23 / 23 / 9
Регистрация: 07.12.2012
Сообщений: 169
Завершенные тесты: 1
29.10.2015, 18:07     Лямбды и захват переменных #10
Renji, std:function может хранить как функцию так и функциональный объект с одинаковой сигнатурой. А лямбда - это безымянный функциональный объект (функтор).
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.10.2015, 20:53     Лямбды и захват переменных
Еще ссылки по теме:

C++ Тело лямбды. Двумерный массив
C++ Прокомментировать код функций, генерирующих другие функции (лямбды)
Не компилится из-за лямбды C++
C++ Как вернуть значение лямбды?
Как создать псевдоним для лямбды? C++

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

Или воспользуйтесь поиском по форуму:
hoggy
6148 / 2514 / 442
Регистрация: 15.11.2014
Сообщений: 5,562
Завершенные тесты: 1
29.10.2015, 20:53     Лямбды и захват переменных #11
Цитата Сообщение от Renji Посмотреть сообщение
Лямбды могут захватывать переменные через [value1,value2]{}. Вопрос: а куда, собственно, эти переменные захватываются - в статический буфер общий для всех вызовов лямбды или в локальный буфер формируемый под каждый вызов и передающийся лямбде на манер this?
лямбда - это обычный класс-функтор.
если лямбда хапанула контекст,
то компилятор сгенерирует функтор с данными-членами.
которые и будут хранить этот контекст.

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

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

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

поэтому, она не заморачивается тем, что под капотом функтора.
просто дергает его оператор()
Yandex
Объявления
29.10.2015, 20:53     Лямбды и захват переменных
Ответ Создать тему
Опции темы

Текущее время: 11:52. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru