Как я могу сделать хранение лямбда-объектов C ++ более эффективным?

В последнее время я думал о хранении лямбда-выражений C ++. Стандартный совет, который вы видите в Интернете, - хранить лямбду в объекте std :: function. Однако ни один из этих советов никогда не рассматривает последствия для хранения. Мне пришло в голову, что за кулисами должно происходить какое-то серьезное вуду, чтобы это сработало.Рассмотрим следующий класс, который хранит целочисленное значение:

class Simple {
public:
    Simple( int value ) { puts( "Constructing simple!" ); this->value = value; }
    Simple( const Simple& rhs ) { puts( "Copying simple!" ); this->value = rhs.value; }
    Simple( Simple&& rhs ) { puts( "Moving simple!" ); this->value = rhs.value; }
    ~Simple() { puts( "Destroying simple!" ); }
    int Get() const { return this->value; }

private:
    int value;
};

Теперь рассмотрим эту простую программу:

int main()
{
    Simple test( 5 );

    std::function<int ()> f =
        [test] ()
        {
            return test.Get();
        };

    printf( "%d\n", f() );
}

Это результат, который я надеюсь увидеть в этой программе:

Constructing simple!
Copying simple!
Moving simple!
Destroying simple!
5
Destroying simple!
Destroying simple!

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

Излишне говорить, что это не то, что я вижу. Когда я компилирую это в Visual C ++ 2010 (в режиме выпуска или отладки), я получаю следующий результат:

Constructing simple!
Copying simple!
Copying simple!
Copying simple!
Copying simple!
Destroying simple!
Destroying simple!
Destroying simple!
5
Destroying simple!
Destroying simple!

Черт побери, это неэффективно! Компилятор не только не смог использовать мой конструктор перемещения, но и сгенерировал и уничтожил две явно лишние копии лямбды во время присваивания.

Итак, вот наконец вопросы: (1) Действительно ли все это копирование необходимо? (2) Есть ли способ заставить компилятор генерировать лучший код? Спасибо за прочтение!

21
задан Peter Ruderman 19 November 2018 в 17:10
поделиться