лямбды и их захваченные ценности

Недавно я проводил некоторые эксперименты с функционально-реактивным программированием и тем, что это такое, и когда я пытался реализовать что-то подобное в c ++, я обратился за помощью к лямбде. Я придумал начало чего-то вроде этого,

template<class T>
class Reactive
{
public:
Reactive(T data)
{
m_Data = data;
}

Reactive(std::function<T()> func, T data)
{
m_Data = data;
m_Affecter = func;
}

template<class H>
Reactive & operator+(const H & rhs)
{
m_Data += rhs;

return *this;
}

template<class H>
Reactive operator+(Reactive<H> & rhs)
{
std::function<decltype(m_Data + rhs.m_Data)()> func;

if (!rhs.m_Affecter)
func = [&](){return m_Data + rhs.m_Data;};
else
func = [&](){return m_Data + rhs.m_Affecter();};

return Reactive<decltype(m_Data + rhs.m_Data)> (func, m_Data + rhs.m_Data);
}

Reactive & operator=(const T & data)
{
m_Data = data;

return *this;
}

Reactive & operator=(const Reactive & rhs)
{
m_Data = rhs.m_Data;
m_Affecter = rhs.m_Affecter;

return *this;
}

T & Get()
{
return m_Data;
}

void Update()
{
m_Data = m_Affecter();
}

private:
std::function<T()> m_Affecter;
T m_Data;
};

Пока что это только добавление поддержки. я пытался создать объект, называемый реактивным, который может обернуться вокруг любого другого типа, за исключением того, что когда над ним выполняется математическая операция, создается лямбда, где эта операция выполняется, чтобы как-то вспомнить, что было сделано до этого, и сделать это снова, когда изменилось одно из влияющих на него значений (после вызова функции обновления). например, если бы я должен был сделать это.

Reactive<int> cheh = 0;
Reactive<int> meh = 3;
Reactive<int> peh = 7;
cheh = meh + peh;
meh = meh + 4;
cheh.Update();
std::cout << cheh.Get();

тогда вот что будет. суммирование двух реактивов в строке пять сделало бы еще один реактив с двумя добавленными к 10 значениями, а также установил бы его аффектор к лямбде, который делает что-то вроде этого, &{meh.m_Data + peh.m_Data}. Тогда этот реактив будет назначен на cheh. Когда к значению m_meh было добавлено 4, и cheh был обновлен, его аффектор был вызван с новым значением 14, и это то, что выводится на экран, именно так, как я и предполагал.

Но потом я подумал, а что, если один из тех реактивов, которые участвуют в воздействии Чеха, выходит из-под контроля? Программа должна выдавать ошибку, если не обрабатывается правильно.
Итак, я сделал это,

Reactive<int> cheh = 0;
Reactive<int> meh = 3;

{
Reactive<int> peh = 7;
cheh = meh + peh;
peh = peh + 4;
}

cheh.Update();
std::cout << cheh.Get();

В тот момент, когда вызывается обновление, Reactive peh, имевший место в его аффекте, вышел из области видимости и больше не существует. Тем не менее, эта программа и ахэктер cheh успешно выполняются и выводит 14, как и раньше. Я знаю, что значения в лямбда-выражениях были переданы захватом ссылки, так как же функция affecter может по-прежнему обращаться к ссылке на peh? Заставляет ли объект или целочисленный тип, передаваемый в лямбду, посредством ссылки, их сохранение до тех пор, пока существует лямбда? Что-то пахнет рыбой …

0

Решение

Я знаю, что значения в лямбда-выражениях были переданы захватом ссылки, так как же функция affecter может по-прежнему обращаться к ссылке на peh? Заставляет ли объект или целочисленный тип, передаваемый в лямбду, посредством ссылки, их сохранение до тех пор, пока существует лямбда? Что-то пахнет рыбой …

Программа имеет неопределенное поведение. Захват по ссылке, как вы подозреваете, делает не продлить время жизни объектов, с которыми связаны эти ссылки, и разыменовывать ссылку на объект, который больше не существует, — UB.

Однако неопределенное поведение не обязательно означает, что произойдет сбой. Возможно (как, кажется, имеет место здесь), что программа будет просто казаться работать нормально. Это может быть неверно на другом компьютере или после перезагрузки компьютера.

Также см это блестящее объяснение почему может показаться, что к объектам можно получить доступ даже после того, как они выпали из области видимости.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]