Почему эта лямбда в C ++ включает в себя все ссылки? - PullRequest
5 голосов
/ 07 июня 2019

Скомпилируйте с g++.exe -m64 -std=c++17 и любым уровнем оптимизации и запустите:

#include <iostream>

int main() {
    const auto L1 = [&](){};
    std::cout << sizeof(L1) << std::endl;
    const auto L2 = [&](){L1;};
    std::cout << sizeof(L2) << std::endl;
    const auto L3 = [&](){L1, L2;};
    std::cout << sizeof(L3) << std::endl;
    const auto L4 = [&](){L1, L2, L3;};
    std::cout << sizeof(L4) << std::endl;
}

Вывод будет 1,8,16,24, что означает, что L2 содержит 1 ссылку, L3 содержит 2 и L4 содержит 3.

Однако, учитывая ту же функцию "[&](){L1, L2;} в main()", значение &L1 - &L2 должно быть фиксированным, и для использования L1 с указателем на L2, есть прямая адресация в x86 [rbx+const] при условии rbx=&L2.Почему GCC по-прежнему предпочитает включать каждую ссылку в лямбду?

1 Ответ

1 голос
/ 07 июня 2019

Я думаю, что это пропущенная оптимизация, поэтому вы можете сообщить о ней как об ошибке gcc на https://gcc.gnu.org/bugzilla/. Использовать ключевое слово пропущенной оптимизации.

Захватывающая лямбда-функция не является для нее функциейсобственный, и не может распадаться / преобразовываться в указатель на функцию, так что я не думаю, что есть какой-либо обязательный макет для лямбда-объекта.( Использовать лямбду в качестве параметра для функции C ++ ).Сгенерированный код, который читает лямбда-объект, всегда будет генерироваться из того же модуля компиляции, который его определил.Таким образом, звучит правдоподобно, что для всех локальных источников нужен только один базовый указатель со смещениями.

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


Вы можете получить компилятор для использования пробела и создать лямбда-объект в памяти, передав лямбду в __attribute__((noinline)) шаблонная функция.https://godbolt.org/z/Pt0SCC.

...