Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 | страница 37
>std::function
, которая имеет фиксированный размер для каждой заданной сигнатуры. Этот размер может быть не адекватным для замыкания, которое требуется хранить, и в этом случае конструктор >std::function
будет выделять для хранения замыкания динамическую память. В результате объект >std::function
использует больше памяти, чем объект, объявленный с помощью >auto
. Кроме того, из-за деталей реализации это ограничивает возможности встраивания и приводит к косвенным вызовам функции, так что вызовы замыкания через объект >std::function
обычно выполняются медленнее, чем вызовы посредством объекта, объявленного как >auto
. Другими словами, подход с использованием >std::function
в общем случае более громоздкий, требующий больше памяти и более медленный, чем подход с помощью >auto
, и к тому же может приводить к генерации исключений, связанных с нехваткой памяти. Ну и, как вы уже видели в примерах выше, написать “>auto
” — гораздо проще, чем указывать тип для инстанцирования >std::function
. В соревновании между >auto
и >std::function
для хранения замыкания побеждает >auto
. (Подобные аргументы можно привести и в пользу предпочтения >auto
перед >std::function
для хранения результатов вызовов >std::bind
, но все равно в разделе 6.4 я делаю все, чтобы убедить вас использовать вместо >std::bind
лямбда-выражения...)Преимущества >auto
выходят за рамки избегания неинициализированных переменных, длинных объявлений переменных и возможности непосредственного хранения замыкания. Кроме того, имеется возможность избежать того, что я называю проблемой “сокращений типа” (type shortcuts). Вот кое-что, что вы, вероятно, уже видели, а возможно, даже писали:
>std::vector
>…
>unsigned sz = v.size();
Официальный возвращаемый тип >v.size()
— >std::vector
, но об этом знает не так уж много разработчиков. >std::vector
определен как беззнаковый целочисленный тип, так что огромное количество программистов считают, что >unsigned
вполне достаточно, и пишут исходные тексты, подобные показанному выше. Это может иметь некоторые интересные последствия. В 32-разрядной Windows, например, и >unsigned
, и >std::vector
имеют один и тот же размер, но в 64-разрядной Windows >unsigned
содержит 32 бита, а >std::vector
— 64 бита. Это означает, что код, который работал в 32-разрядной Windows, может вести себя некорректно в 64-разрядной Windows. И кому хочется тратить время на подобные вопросы при переносе приложения с 32-разрядной операционной системы на 64-разрядную?