Поддерживает ли boost:: any/std:: какие-либо мелкие объекты на складе?

Чтобы удерживать произвольно большие объекты, boost::any/std::any наверняка нужно выделить кучу пространства для объектов. Однако для небольших типов, размер которых меньше или равен указателю (int,char,bool,...), any может вместо этого сохранить значение на месте в слоте указателя или в какой-либо другой локальной памяти и не выделять кучу пространства. Но делает ли это выполнение?

У меня есть сценарий, в котором я часто храню небольшие типы в any и только иногда более крупные типы, такие как string s. Код довольно жаркий, и поэтому я задаю вопрос. Если оптимизация не выполняется, мне может быть лучше с собственной реализацией, которая хранит небольшие типы на месте.

Ответ 1

Нет гарантии, но в проекте С++ 17 указано [any.class], что

Реализации должны избегать использования динамически распределенной памяти для небольшого содержащегося объекта. [Пример: где построенный объект содержит только int. - end example] Такая оптимизация небольших объектов должна применяться только к типам T, для которых is_­nothrow_­move_­constructible_­v<T> - true.

К сожалению, он не дает рекомендации относительно того, что следует считать маленьким, за исключением того, что int должен быть сохранен на месте.

Ответ 2

Если я правильно понимаю исходный код Boost.Any и от того, что он отталкивает его в отладчике, он не применяет оптимизацию небольших объектов. (Обратите внимание на безусловное использование нового.)

    template<typename ValueType>
    any(const ValueType & value)
      : content(new holder<
            BOOST_DEDUCED_TYPENAME remove_cv<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>::type
        >(value))
    {
    }

Ответ 3

Ответы Натана Оливера и Джоша Келли верны: нет никакой гарантии, boost не использует оптимизацию небольших значений.

В более практических случаях, https://github.com/llvm-mirror/libcxx/blob/master/include/experimental/any#L129 Показывает, что libС++ (clang's) дает вам 3 указателя void, стоящие на пробел, (24 байта, если они имеют ширину 8 байтов)

libstdС++ только один указатель: https://gcc.gnu.org/viewcvs/gcc/trunk/libstdc%2B%2B-v3/include/experimental/any?view=markup#l106

Изменение any, чтобы сделать параметр шаблона не сложным, просто убедитесь, что существует возможность конвертирования между any разных размеров.

IMO, разница в производительности настолько существенна между оптимизацией небольшого размера и распределением кучи в соответствии с моими критериями и стоимостью реализации, чтобы сделать его настолько малым, что он станет частью стандартного