Страницы

Поиск по вопросам

среда, 29 января 2020 г.

Лямбда выражения и функторы в стандартных алгоритмах

#cpp #алгоритм #лямбда_выражение


Опишите пожалуйста плюси и минусы  вариантов  для конкретно этого примера(применение
в std::for_each) , и когда и почему лямбда имеет преимущество(или наоборот)  по отношению
к функтору:

 ...
void f(const int value)
{
    cout << value << endl;
}

int main()
{    
    vector v{1, 2, 3, 4, 5};
    function op(&f) ; // функтор
    auto p = [](const int i) { return f(i + 5); }; // лямбда
    for_each(v.begin(), v.end(), op); // первый вариант
    for_each(v.begin(), v.end(), p);   // второй вариант
    ...
}

    


Ответы

Ответ 1



В качестве вишенки :) Создаю вектор и иже с ним: void f(int value) { sum += value; } const int Count = 100000000; vector v(Count); generate(v.begin(),v.end(),g); function op(&f); Затем просто суммирую в глобальную переменную: for_each(v.begin(),v.end(),f); for_each(v.begin(),v.end(),[](const int i) { sum += i; }); for_each(v.begin(),v.end(),op); VC++2017 дал на моей машине следующие времена (в мс) - 187, 41 и 208 соответственно. Ideone дает примерно те же результаты. P.S. Явное создание struct Sum { void operator()(int value) { sum += value; } }; как и следовало ожидать, от лямбды ничем не отличается.

Ответ 2



Ну, во-первых, в такой ситуации вы можете передавать в алгоритм прямо сразу f. Никакой оболочки вокруг f из лямбды или из std::function тут формально не требуется. (Разумеется, если вы хотите прибавить 5 к аргументу, то лямбда - именно то, что надо.) Во-вторых, при создании, удалении и на каждом вызове std::function тянет за собой накладные расходы, связанные с затратами на type erasure внутри std::function. Поэтому передавать std::function лучше только туда, где на входе требуется именно std::function. std::function предназначен в первую очередь для устранения зависимости принимающего алгоритма от шаблонного параметра, описывающего тип функтора. В вашем случае, т.е. для std::for_each, никакой речи о таком устранении не идет: в std::for_each тип функтора уже присутствует в списке шаблонных параметров, никто его не устранял и устранять не собирается. И поэтому платить накладные расходы за std::function нет никакого смысла. Лямбда тут будет работать эффективнее. Это относится ко всем стандартным алгоритмам: у них у всех типы функторов, предикатов, компараторов и т.п. вынесены в список параметров шаблона. В такой ситуации нет смысла использовать std::function без каких-то дополнительных/посторонних на то причин.

Комментариев нет:

Отправить комментарий