Хранение лямбды в классе - PullRequest
0 голосов
/ 31 января 2012

Какую наилучшую практику использовать, когда нужно хранить лямбду в качестве члена класса, чтобы ее вызов мог быть отложен? В частности, безопасно ли хранить лямбду, переданную классу deferred_lambda в приведенном ниже листинге кода, в качестве ссылки? Если нет, то будет ли безопасно хранить лямбду в deferred_lambda как значение, а не как ссылку?

Наконец, могу ли я ожидать снижения производительности по сравнению с обычным вызовом функции с g ++ для хранения лямбды в качестве члена класса таким образом? То есть будет ли deferred_lambda.invoke() медленнее, чем вызов operator() в некоторой фиктивной структуре, которая будет реализовывать те же операции?

С g ++ я заметил, что размер лямбды увеличивается, когда я использую больше захваченных переменных. Я полагаю, что этого следовало ожидать, поскольку, насколько я понимаю, компилятор внутренне генерирует структуру для лямбда-выражения, которая содержит необходимые захваченные переменные в качестве членов. Это наблюдение привело к вопросу, который я сейчас задаю, поскольку хранение лямбда-выражений по значению может быть более дорогим с точки зрения времени и памяти, чем хранение ссылок на них.

template <class Func>
class deferred_lambda
{
    Func& func_;
public:
    deferred_lambda(Func func) : func_(func) {}
    void invoke() { func_(); }
};

template <class Func>
deferred_lambda<Func> defer_lambda(Func func)
{
    return deferred_lambda(func);
}

void foo()
{
    int a, b, c;
    auto x = defer_lambda([&]() { a = 1; b = 2; c = 3; });
} 

Ответы [ 2 ]

7 голосов
/ 31 января 2012

Я считаю, что способ сохранить лямбду для последующего выполнения - использовать объект std::function.В зависимости от реализации библиотеки класс function должен иметь необходимые конструкторы и преобразователи, чтобы иметь лямбду или любой другой вид функтора или функции, назначенный ему для последующего выполнения.

4 голосов
/ 31 января 2012

В частности, безопасно ли хранить лямбду, переданную классу deferred_lambda в приведенном ниже листинге кода, в качестве ссылки?

Нет.Это будет зависшая ссылка после того, как defereed_lambda() закончится.

Если нет, было бы безопасно, если бы я сохранял лямбда-выражение в deferred_lambda как значение, а не как ссылку?

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

То есть использование deferred_lambda.invoke () будет медленнее, чем вызов оператора () в некоторой фиктивной структуре, котораябудет выполнять те же операции?

Вероятно, нет, для этого нет никаких оснований.

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

Оно все равно должно храниться где-то ...

...