libc++源码分析之std::__compressed_pair

compressed_pair

与pair相比,compressed_pair提供了空类优化,节省了空类的内存

pair

看pair的实现可以看到,将first和second都作为属性进行保存。

1
2
3
4
5
6
7
8
9
template <class _T1, class _T2>
struct _LIBCPP_TEMPLATE_VIS pair : private __non_trivially_copyable_base<_T1, _T2>
{
typedef _T1 first_type;
typedef _T2 second_type;

_T1 first;
_T2 second;
}

示例

在下面的例子中,对于pair来说,A和B都是其属性,A类是空类,sizeof为1,B类sizeof为4,字节对齐后,整个pair是8,这就是空类所带来的内存浪费。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A {

};

class B {
int b;
};

int main(int argc, char const* argv[]) {
std::pair<A, B> p;
int size = sizeof(p); // 8

std::__compressed_pair<A, B> cp;
int size2 = sizeof(cp); // 4
return 0;
}

compressed_pair

compressed_pair通过继承优化了空类所带来的内存浪费,在上面的例子中compressed_pair继承了A和B,对于compressed_pair来说只有基类B有一个int属性,所以sizeof为4。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <class _T1, class _T2>
class __compressed_pair : private __compressed_pair_elem<_T1, 0>,
private __compressed_pair_elem<_T2, 1> {
public:
typedef _LIBCPP_NODEBUG_TYPE __compressed_pair_elem<_T1, 0> _Base1;
typedef _LIBCPP_NODEBUG_TYPE __compressed_pair_elem<_T2, 1> _Base2;

template <class _U1, class _U2>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
__compressed_pair(_U1&& __t1, _U2&& __t2)
: _Base1(_VSTD::forward<_U1>(__t1)), _Base2(_VSTD::forward<_U2>(__t2)) {}

_LIBCPP_INLINE_VISIBILITY
typename _Base1::reference first() _NOEXCEPT {
return static_cast<_Base1&>(*this).__get();
}

_LIBCPP_INLINE_VISIBILITY
typename _Base2::reference second() _NOEXCEPT {
return static_cast<_Base2&>(*this).__get();
}

};