Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.72/25: Рейтинг темы: голосов - 25, средняя оценка - 4.72
69 / 57 / 14
Регистрация: 20.12.2013
Сообщений: 656
1

Время жизни лямбда-функции

25.12.2017, 20:09. Показов 4951. Ответов 4
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
A lambda might outlive its caller/ This can happen if we pass a lambda to a different thread or the callee stores away the lambda for latest use. For example:
C++
1
2
3
4
5
void setup(Menu& m)
{
 
Point p1, p2, p3;
m.add("draw triangle", [&]{m.draw(p1,p2,p3);}}
Не пойму, здесь сохраняется ведь указатель на лямбда-функцию? А при выходе из области почему не происходит удаления тела функции, введенной локально, с указанием указателя на неизвестную область памяти?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.12.2017, 20:09
Ответы с готовыми решениями:

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

C++11 время жизни переменных
После долгого перерыва в программирование вновь спохватился и тут наткнулся на такую не ожиданность...

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

Время жизни объектов
Вроде простая вещь, а не могу понять почему так. #include <iostream> using namespace std; ...

4
7796 / 6562 / 2985
Регистрация: 14.04.2014
Сообщений: 28,699
25.12.2017, 22:03 2
Почему указатель? Она как объект.
0
69 / 57 / 14
Регистрация: 20.12.2013
Сообщений: 656
26.12.2017, 02:58  [ТС] 3
Цитата Сообщение от nmcf Посмотреть сообщение
Почему указатель? Она как объект.
Да, в книге написано, что можно считать ее функциональным объектом, но есть и такая фраза:
A lambda that captures nothing can be assigned to a pointer to function of an appropriate type.
А если "плавает как утка, выглядит как утка, крякает как утка, то ...".
Вопрос из следующего возник: привел тут на форуме одно решение, сокращенно
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class action
{
    std::string str;     //Ответ для формулировки действия
    void(*fun)(std::string ss);
public:
    action(void(*f)(std::string ss) = 0) : fun(f) {};
    void operator()(std::string s){ str = s; fun(str); return; };
};
 
void check_age(std::string ss)
{
//
};
 
vector<pair<std::string, action*>> ans;  //сохраняется пара<ответ, действие>
std::string str2, cur_str;
char buf[200];
 
int main() {
    
    setlocale(LC_ALL, "C");
 
    //Ввод исходных данных
    ans.push_back(make_pair<std::string, action*>("To be (y) , or not to be (n) ?", new action(
                            [](std::string ss) { ss == std::string{ "y" } ? std::cout << "Ok." << '\n' << '\n' : std::cout << "The answer is wrong." << '\n' << '\n'; })));
        ans.push_back(make_pair<std::string, action*>("How old are you?", new action(check_age)));
 
    //...
    //Диалог
    cout << "Hello." << '\n';
    for (auto vaL : ans)
    {
        std::cout << vaL.first<<'\t';
        std::cin>>str2;
        (*vaL.second)(str2);
        delete vaL.second;
    };
Т.е. с помощью new создается объект типа action, и в него передается лямбда-функция через указатель на функцию, дальше в цикле for происходит использование, и это работает. Но теперь не могу понять: для цикла for по объектам функтор уже не в зоне видимости, т.е. если я передал указатель, то объект уже должен быть удален, и указатель указывает на в общем случае неизвестно что? Вот если бы копировался объект, то понятно, но передача через указатель... Это чисто случайно получилось, что программа работает, или так и должно быть?

Добавлено через 34 минуты
p.s. Т.е. похоже, что в случае передачи как указателя передается указатель на operator(), но это ничего не проясняет.
Вот сейчас изменил код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class action
{
        std::string str;     //Ответ для формулировки действия
    void(*fun)(std::string ss);
    function<void(std::string ss)> lam; //ДОБАВЛЕНО!!!!!!!!!!!!!!!
public:
    action(function<void(std::string ss)> lam_, void(*f)(std::string ss) = 0) : fun(f), lam(lam_) {};  //ДОБАВЛЕН ПЕРВЫЙ АРГУМЕНТ И ЕГО ИНИЦИАЛИЗАЦИЯ!!!!!!!!!!!!!!!
    void operator()(std::string s) { str = s; /*fun(str);*/lam(str); return; };
};
 
void check_age(std::string ss)
{
//
};
 
vector<pair<std::string, action*>> ans;  //сохраняется пара<ответ, действие>
std::string str2, cur_str;
char buf[200];
 
int main() {
    
    setlocale(LC_ALL, "C");
 
    //Ввод исходных данных
    ans.push_back(make_pair<std::string, action*>("To be (y) , or not to be (n) ?", new action(
                            [](std::string ss) { ss == std::string{ "y" } ? std::cout << "Ok." << '\n' << '\n' : std::cout << "The answer is wrong." << '\n' << '\n'; })));
    ans.push_back(make_pair<std::string, action*>("How old are you?", new action(check_age)));
 
    //...
    //Диалог
    cout << "Hello." << '\n';
    for (auto vaL : ans)
    {
        std::cout << vaL.first<<'\t';
        std::cin>>str2;
        (*vaL.second)(str2);
        delete vaL.second;
    };
Т.е. теперь передается как function<void(std::string ss)> . Результат выполнения тот же.
Но функция check_age тоже передалась через function<void(std::string ss)> - значит function<void(std::string ss)> тоже указатель на функцию?!

Добавлено через 10 минут
C++
1
2
3
4
5
6
void setup(Menu& m)
{
 
Point p1, p2, p3;
m.add("draw triangle", [&]{m.draw(p1,p2,p3);}}
}
If a lambda might outlive its caller, we must make sure that all local information (if any) is copied into the closure object and that values are returned through the return mechanism.
C++
1
m.add("draw triangle", [=]{m.draw(p1,p2,p3);}
Как я вижу, лямбда передается только как указатель (хз как в случае использования auto, ну да здесь это не прокатит). Так лямбда - всегда статический объект? Или это "умный указатель", который предотвращает удаление объекта?

Добавлено через 7 минут
pps Если нужен рабочий текст программы для проверки, то он здесь "Да" и "нет" в качестве величины переменной
0
277 / 226 / 93
Регистрация: 27.06.2016
Сообщений: 639
26.12.2017, 05:20 4
AndrSlav, сложно вас читать...
"почему не происходит удаления тела функции" - тело функции - это код, статическая информация, оно во время выполнения ни создаётся, ни удаляется. В этом нет никакого смысла.
0
249 / 219 / 63
Регистрация: 30.07.2013
Сообщений: 465
26.12.2017, 10:55 5
Лучший ответ Сообщение было отмечено AndrSlav как решение

Решение

Реализация лямбд зависит от компилятора. Но для понимания можно считать, что для лямбды компилятор сам создает класс-функтор с автоматически сгенерированным и неизвестным человеку именем (поэтому лямбды объявляются с auto).
C++
1
2
3
4
5
6
7
auto lambda = [] (int a) { return a + 3; };
...
class Functor
{
public:
    int operator()(int a) { return a + 3; }
};
Для лямбд с захватом переменных (по значению или по ссылке)
C++
1
2
3
4
5
6
7
8
9
10
11
int x = 3;
auto lambda = [&x] (int a) { return a + x++; };
...
class Functor
{
public:
    Functor(int& x): m_x(x) {}
    int operator()(int a) {return a + m_x++;}
private:
    int& m_x;
};
Соответсвенно, у объекта лямбды с захватом есть состояние и такие лямбды не могут быть приведены к типу простого указателя на функцию. При передаче во всякие функции такие лямбды, т.е. соответствующие объекты-функторы, передаются по значению, т.е. копируются.

А у лямбды без захвата нет состояния, можно просто взять указатель на метод operator() соответствующего класса-функтора. Даже объект создавать не надо (может, компилятор даже его статическим делает). И хранится в указателе на функцию именно указатель на этот метод. Сам метод, его код - повторяю - скрыт от человека.
1
26.12.2017, 10:55
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.12.2017, 10:55
Помогаю со студенческими работами здесь

Время жизни объекта класса
Всем привет! Вот возник у меня вопросс с ООП и разработкой больших программ. Большие ООП...

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

Время жизни временного объекта
можно ли передать временный объект в функцию по ссылке? void f1(int &amp; ); ..... int...

Время жизни переменной и присваивание
Здравствуйте, int my_func() { int a=5; return a; }


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru