[英]std::make_unique's (and emplace, emplace_back's) awkward deduction for initializer_list arguments
[英]emplace_back in a list from a unique_ptr
这不编译
std::list<int> l;
std::unique_ptr<int> p = std::make_unique<int>();
l.emplace_back(std::move(p));
列表的内部存储是_List_node
,它只是指向底层数据的简单来回指针,这里是int
。 因此,列表可以窃取unique_ptr
的内部指针并将其放回原处。
在我的完整用例中,我有一个大于int
的对象列表,并且我使用这样的移动构造函数
l.emplace_back(std::move(*p));
但这比窃取unique_ptr
的指针要慢,因为我的底层类型的许多字段都被复制了。
为什么列表不接受从unique_ptr
移动,还有另一个容器可以接受吗?
所以列表可以窃取 unique_ptr 的内部指针
不,它不能。 列表分配存储元素的节点。 元素类型的 object 对它没有用处。
只有 std::list 可以从另一个相同类型的std::list
std::list
中窃取元素。
为了避免移动,要么首先创建 object 作为列表的元素,要么不要尝试将其存储在一个列表中。 将 object 放在一处。
在移动速度很快的情况下——对于大多数类型来说, std::move(*p)
就可以了。
_List_node
的典型实现如下所示:
template<typename _Tp>
struct _List_node : public __detail::_List_node_base
{
#if __cplusplus >= 201103L
__gnu_cxx::__aligned_membuf<_Tp> _M_storage;
_Tp* _M_valptr() { return _M_storage._M_ptr(); }
_Tp const* _M_valptr() const { return _M_storage._M_ptr(); }
#else
_Tp _M_data;
_Tp* _M_valptr() { return std::__addressof(_M_data); }
_Tp const* _M_valptr() const { return std::__addressof(_M_data); }
#endif
};
并且__alignment_membuf
看起来大致是这样的:
template<typename _Tp>
struct __aligned_membuf
{
struct _Tp2 { _Tp _M_t; };
alignas(__alignof__(_Tp2::_M_t)) unsigned char _M_storage[sizeof(_Tp)];
};
因此,存储在列表中的数据作为_M_data
/ _M_storage
成员变量完全包含在_List_node
中(_List_node 只有一个_Tp
分配, _List_node
没有额外的分配)。
因此,列表节点没有指向它管理但包含它的数据的指针。
因此,没有办法窃取指针,存储在列表中的类型必须始终移动或复制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.