boost::any / std::any 是否就地存储小对象?

Does boost::any / std::any store small objects in-place?

要容纳任意大的对象,boost::any / std::any 肯定需要为对象分配堆 space。但是,对于大小小于或等于指针 (int,char,bool,...) 的小型类型,any 可以将值就地存储在指针槽或其他一些就地内存中,而不分配堆space。但是实现会这样做吗?

我有一个场景,我经常将小类型存储在 any 中,有时只存储大类型,如 strings。代码很热,因此我要问这个问题。如果不执行优化,我可能会更好地使用自己的实现来存储小类型。

无法保证,但 C++17 草案在 [any.class] 中声明

Implementations should avoid the use of dynamically allocated memory for a small contained object. [ Example: where the object constructed is holding only an int.  — end example ] Such small-object optimization shall only be applied to types T for which is_­nothrow_­move_­constructible_­v<T> is true.

不幸的是,它没有给出应该考虑什么的建议 small 除了说 int 应该能够存储在适当的位置。

如果我正确理解 Boost.Any 源代码,并在调试器中查看它,它不会应用小对象优化。 (注意无条件使用new。)

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

Nathan Oliver 和 Josh 的 Kelley 的回答是正确的:不能保证,boost 不使用小值优化。

在更实际的情况下, https://github.com/llvm-mirror/libcxx/blob/master/include/experimental/any#L129 向您展示 libc++(clang 的)为您提供了 3 个价值 space 的空指针,(如果它们的宽度为 8 个字节,则为 24 个字节)

libstdc++只有一个指针: https://gcc.gnu.org/viewcvs/gcc/trunk/libstdc%2B%2B-v3/include/experimental/any?view=markup#l106

更改 any 使大小成为模板参数并不困难,只是您还应确保不同大小的 any 之间存在可转换性。

IMO,根据我的基准测试,小尺寸优化和堆分配之间的性能差异如此之大,而且将其制作成如此小的模板的实现成本将成为标准的一部分