Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
gromo
372 / 271 / 30
Регистрация: 04.09.2009
Сообщений: 1,214
1

Lambda Capture — extending object's lifetime

23.11.2015, 23:23. Просмотров 363. Ответов 7
Метки нет (Все метки)

Всем привет!
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
// --- Поясняющий псевдокод.
void SomeClass::func(Movable m)
{
    Attribute& attr = m.getAttribute();
 
    if(!attr.empty())
    {
        auto do_deferred_analyze = [&, m = std::move(m), this](const Reply& tcpRequestReply)
        {
            // NOTE: Вызов этой лямбды, вероятно, будет отложен,
            // то есть она вызовется после того,
            // как SomeClass::func завершится.
 
            // --- Вопрос: безопасно ли здесь использовать, захваченный по
            // ссылке `attr'?
            // По сути, внутреннее состояние, на которое ссылается 
            // `attr' не разрушено, ведь `m' перемещен внутрь лямбды.
 
            for(const auto& element : atrr) // Possible crash?
                doSomething(tcpRequestReply[element]);
        };
        
        makeAsyncNetworkRequest() {
            // . . .
            // . . .
            do_deferred_analyze(reply);
        };
    }
}
Вся затея для того, чтобы избежать бессмысленного дублирования кода получения атрибута внутри лямбды, ибо я обращаюсь к атрибуту attr и вне лямбды, и внутри лямбды. Таких атрибутов у меня несколько, поэтому реально дублирующегося кода гораздо больше, чем в коде выше.

P.s. В таком варианте у меня на данный момент все работает, crash'ы не наблюдаются, но хотелось бы знать наверняка, чтобы избежать сюрпризов в будущем

Инструментарий:
Bash
1
2
3
4
5
~$ uname -a
Linux x 4.2.5-1-ARCH #1 SMP PREEMPT Tue Oct 27 08:13:28 CET 2015 x86_64 GNU/Linux
~$ gcc --version
gcc (GCC) 5.2.0
Copyright (C) 2015 Free Software Foundation, Inc.
Добавлено через 12 минут
___
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.11.2015, 23:23
Ответы с готовыми решениями:

Variadic template lambda capture
Доброго всем дня! Речь пойдёт об C++14, в котором стало возможным делать...

Lambda init capture by const reference
Всем привет. Почему не получается добиться следующего поведения: auto...

Ошибки: capture of non-variable Game::templog, 'this' was not captured for this lambda function
Пытаюсь очистить вектор mainlog от записей, встречающихся в векторе templog....

литература shared objects & dynamic shared objects
Привет, товариСЧи. Подкиньте пожалуйста пару тройку книженций по теме инглиш...

Lambda crash
Есть класс в продакшне. В одном из методов (они все static) обьявляю лямбду, в...

7
Croessmah
++Ͻ
14740 / 8422 / 1597
Регистрация: 27.09.2012
Сообщений: 20,714
Записей в блоге: 2
Завершенные тесты: 1
23.11.2015, 23:25 2
Ссылка на один объект, а перемещены данные во второй объект, так что здесь, скорее зависит всё от устройства этих объектов.
Например:
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
#include <iostream>
 
 
 
struct Test
{
    int & getAttr() { return x ; }
    int x ;
} ;
 
 
 
int main()
{
    Test t ;
    t.x = 10 ;
    int & x_ref = t.getAttr() ;
 
    auto fn = [ & , t = std::move(t) ]
    {
        x_ref = 15 ; 
        std::cout << "value: " << x_ref << " address:" << &x_ref << std::endl ;
        std::cout << "value: " << t.x << " address:" << &t.x << std::endl ;
    } ;
    fn() ;
}
http://ideone.com/o8mdYb
1
gromo
372 / 271 / 30
Регистрация: 04.09.2009
Сообщений: 1,214
23.11.2015, 23:31  [ТС] 3
Croessmah, в моём случае, я никак не изменяю захваченную ссылку внутри лямбды, а только читаю данные. Я думаю, все равно будет небезопасно?
В качестве Movable у меня std::tuple, а он, как я понимаю, не использует динамическую аллокаци, так что надеяться на идентичность внутренних адресов после перемещения бесполезно?
UPDATE: хотя нет, tuple использует аллокатор: http://en.cppreference.com/w/cpp/utility/tuple/uses_allocator
0
Croessmah
++Ͻ
14740 / 8422 / 1597
Регистрация: 27.09.2012
Сообщений: 20,714
Записей в блоге: 2
Завершенные тесты: 1
23.11.2015, 23:39 4
Цитата Сообщение от gromo Посмотреть сообщение
а только читаю данные
опять же, если ссылка на уже удаленные данные, то это крах, но, неизвестно как у Вас устроен объект. Может у Вас getAttribute возвращает ссылку на объект Attribute, находящийся в куче и при перемещении лишь указатель перемещается в новый объект, а в старом всё затирается. Тогда уничтожение старого объекта никак не повлияет ни на эти данные, ни на ссылку.
0
rikimaru2013
C++ Game Dev
2472 / 1141 / 348
Регистрация: 30.11.2013
Сообщений: 3,709
24.11.2015, 00:05 5
Croessmah, и зачем самоприсвоение?
C++
1
t = std::move(t)
0
gromo
372 / 271 / 30
Регистрация: 04.09.2009
Сообщений: 1,214
24.11.2015, 21:05  [ТС] 6
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
зачем самоприсвоение?
Это не присвоение, а инициализация.

Добавлено через 22 минуты
В итоге решил продублировать код — от греха подальше, к портабельности — поближе

Добавлено через 16 часов 44 минуты
Цитата Сообщение от Croessmah Посмотреть сообщение
если ссылка на уже удаленные данные, то это крах, но, неизвестно как у Вас устроен объект.
Если допустить, что объект устроен "хорошо" и перемещение не инвалидирует ссылки на внутреннее состояние (оно в куче, например), то что насчёт самого объекта-ссылки attr?
Внутри лямбды он будет валиден или возникнет ситуация, когда мы ссылаемся на валидные данные через невалидную ссылку-объект attr?
0
rat0r
4 / 52 / 10
Регистрация: 16.02.2018
Сообщений: 271
27.08.2018, 04:12 7
Цитата Сообщение от gromo Посмотреть сообщение
или возникнет ситуация, когда мы ссылаемся на валидные данные через невалидную ссылку-объект attr?
"ссылка-объект" — это, конечно, сильно. Ну да ладно. Учитывая дату темы, 14-й стандарт:
Цитата Сообщение от ISO/IEC 14882:2014(E) 5.1.2 Lambda expressions [expr.prim.lambda] p. 24
[ Note: If an entity is implicitly or explicitly captured by reference, invoking the function call operator of
the corresponding lambda-expression after the lifetime of the entity has ended is likely to result in undefined
behavior. — end note ]
0
Operok
178 / 176 / 66
Регистрация: 15.02.2015
Сообщений: 509
Завершенные тесты: 2
27.08.2018, 11:09 8
Если move ctor/assign у Movable определены верно и getAttribute возвращает ссылку на тип стандартного контейнера (или иного, с верно определенными move ctor/assign), то краша не будет, в лямбде будет видна ссылка на пустой контейнер.
При перемещении объекта старый объект остаётся валидным (контейнер будет пустым, поток не joinable, unique_ptr пустым), и при move assign объект получает внутренности другого объекта.

Не по теме:

сори ха некропостинг, не заметил дату темы

0
27.08.2018, 11:09
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.08.2018, 11:09

Rvalue reference and lambda
void foo(A&amp;&amp; a) { auto l = () {}; //a? } Как передать в лямбду...

C++0x lambda (функция qSort не ест компаратор)
Здравствуйте, у меня проблема: функция qSort не ест компаратор, если он...

Deprecated in C++11, Function objects
У меня возник небольшой вопрос по поводу некоторых функциональных объектов в...


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

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

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