能否避免boost::type_erasure::any移动时的内存分配?
Boost.TypeErasure any移动构造时的内存分配能否避免?
在以下测试用例中,移动boost::type_erasure::any对象时会触发动态内存分配:
#include <boost/type_erasure/any.hpp> #include <string> int main() { typedef ::boost::mpl::vector< boost::type_erasure::destructible<>, boost::type_erasure::constructible<boost::type_erasure::_self( boost::type_erasure::_self&&)> > my_concept; typedef boost::type_erasure::any<my_concept> my_any; my_any a1(std::string("Test")); my_any a2 = std::move(a1); // 此处触发动态内存分配 }
这段代码中,a2的移动构造会调用boost/type_erasure/constructible.hpp中的逻辑分配内存:
template<class R, class... T> struct constructible<R(T...)> { static ::boost::type_erasure::detail::storage apply(T... arg) { ::boost::type_erasure::detail::storage result; result.data = new R(::std::forward<T>(arg)...); return result; } };
原本期望通过移动语义直接接管原对象的存储以避免new操作,但调试和基准测试都确认了内存分配的存在,且未找到对应的内置concept优化该场景。
可以避免,但需要自定义扩展boost::type_erasure的concept和实现,默认的constructible仅负责构造新对象,不会处理any内部存储的转移。具体实现步骤如下:
定义自定义转移所有权的concept
创建一个名为transferable的concept,用于描述直接转移内部存储的操作:struct transferable : ::boost::type_erasure::concept_interface< transferable, ::boost::mpl::vector<>> { virtual void transfer(::boost::type_erasure::detail::storage& target) = 0; };为类型包装器实现该concept
针对any内部的类型包装器,实现transfer方法,直接转移存储指针并清空原存储:template<class T, class Base> struct transferable_impl : Base { void transfer(::boost::type_erasure::detail::storage& target) override { target.data = this->data; this->data = nullptr; } };更新concept集合
修改你的my_concept,加入自定义的transferable:typedef ::boost::mpl::vector< boost::type_erasure::destructible<>, transferable> my_concept;自定义
any的移动构造函数
手动调用transfer方法转移存储,替代默认的constructible逻辑:my_any::my_any(my_any&& other) { ::boost::type_erasure::call(transferable(), other, this->storage_); other.storage_.data = nullptr; // 清空原对象存储,避免重复析构 }
另外,也可以利用boost::type_erasure::any的rebind机制或直接操作内部storage接口来管理所有权转移,但上述自定义concept的方式更贴合库的设计模式。
需要注意:所有被any包装的类型,在存储转移后原对象必须处于可安全析构的状态(符合移动语义的要求),否则会引发未定义行为。
内容的提问来源于stack exchange,提问作者Stefan v.K.
相关产品推荐
相关产品推荐

