Производительность преобразования лямбда в std :: function - PullRequest
3 голосов
/ 28 ноября 2011

Я хотел бы использовать лямбда-функции для асинхронного вызова метода для объекта с подсчетом ссылок:

void RunAsync(const std::function<void()>& f) { /* ... */ }

SmartPtr<T> objPtr = ...
RunAsync([objPtr] { objPtr->Method(); });

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

Следующий код должен демонстрировать это поведение:

#include <functional>

struct C {
    C() {}
    C(const C& c) { ++s_copies; }

    void CallMe() const {}

    static int s_copies;
};

int C::s_copies = 0;

void Apply(const std::function<void()>& fct) { fct(); }

int main() {
    C c;
    std::function<void()> f0 = [c] { c.CallMe(); };
    Apply(f0);
    // s_copies = 4
}

Хотя после этого количество ссылок становится нормальным, я бы хотел предотвратить слишком большое количество операций ссылок по соображениям производительности.Я не уверен, откуда все эти операции копирования.

Есть ли способ добиться этого с меньшим количеством копий моего объекта интеллектуального указателя?

Обновление: Компилятор Visual Studio 2010.

Ответы [ 2 ]

5 голосов
/ 29 ноября 2011

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

Но проблема подсчета ссылок является симптомом копирования, когда move подходит. Как отметили другие в комментариях, MSVC неправильно реализует move. Использование, которое вы описали, требует только перемещения, а не копирования, поэтому никогда не следует трогать счетчик ссылок.

Если вы можете, попробуйте скомпилировать с GCC и посмотреть, исчезнет ли проблема.

2 голосов
/ 29 ноября 2011

Преобразование в std::function должно сделать только ход лямбды. Если это не то, что сделано, возможно, есть ошибка в реализации или спецификации std::function. Кроме того, в приведенном выше коде я вижу только две копии оригинальной c, одну для создания лямбды и другую для создания std::function из нее. Я не вижу, откуда берется дополнительная копия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...