为什么libc的map实现使用了这个联合?

前端之家收集整理的这篇文章主要介绍了为什么libc的map实现使用了这个联合?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
#if __cplusplus >= 201103L

template <class _Key,class _Tp>
union __value_type
{
    typedef _Key                                     key_type;
    typedef _Tp                                      mapped_type;
    typedef pair<const key_type,mapped_type>        value_type;
    typedef pair<key_type,mapped_type>              __nc_value_type;

    value_type __cc;
    __nc_value_type __nc;

    template <class ..._Args>
    _LIBCPP_INLINE_VISIBILITY
    __value_type(_Args&& ...__args)
        : __cc(std::forward<_Args>(__args)...) {}

    _LIBCPP_INLINE_VISIBILITY
    __value_type(const __value_type& __v)
        : __cc(__v.__cc) {}

    _LIBCPP_INLINE_VISIBILITY
    __value_type(__value_type& __v)
        : __cc(__v.__cc) {}

    _LIBCPP_INLINE_VISIBILITY
    __value_type(__value_type&& __v)
        : __nc(std::move(__v.__nc)) {}

    _LIBCPP_INLINE_VISIBILITY
    __value_type& operator=(const __value_type& __v)
        {__nc = __v.__cc; return *this;}

    _LIBCPP_INLINE_VISIBILITY
    __value_type& operator=(__value_type&& __v)
        {__nc = std::move(__v.__nc); return *this;}

    _LIBCPP_INLINE_VISIBILITY
    ~__value_type() {__cc.~value_type();}
};

#else
// definition for C++03...

看起来目的是使__value_type可分配和移动,同时还能够将内容公开为对< const key_type,mapped_type> (这是迭代器的值类型等).但我不明白为什么它需要可分配或可移动,因为我看不出任何理由为什么实现需要复制或移动地图内的节点,或者实际上做除了构造和销毁它们之外的任何事情-place,并重新配置指针.

解决方法

使用自定义分配器时,可能需要将映射(及其内容)移动到新的资源池中.在这种情况下,此重载将提供对键的可移动访问:
__value_type(__value_type&& __v)
    : __nc(std::move(__v.__nc)) {}

密钥已被移动并不重要,因为接下来发生的事情是释放所有节点.

请注意,此用法可能会导致未定义的行为.你通常不能写一个联盟的一个成员然后读另一个. Clang和libc可以做到这一点,只要他们可以在内部保证它不会导致问题(或错误诊断).

不过,他们可能就是这样做的,因为没有合适的替代品.至少,我想不出一个.该标准要求value_type :: first_type是真正的const限定的,所以即使是const_cast也是不允许的.

诀窍是在key_type和mapped_type都是标准布局的情况下符合,因此std :: pair< key_type,mapped_type>和std :: pair< key_type const,mapped_type>根据[class.mem]§9.2/ 16,布局兼容.这看起来有点奇怪,因为函数指的是union的直接成员__cc和__nc,将它留给构造函数来访问包含first和second的公共子序列.标准布局类型的requirements有些限制,但许多常见的键和值类型(例如,std :: string)可能会遇到它们.

猜你在找的C&C++相关文章