番外1 什么?sizeof(list<int>)竟然是24
之前写了这样一段代码,
printf("%d | %d \n", sizeof(std::list<int>), sizeof(std::list<long long>));
/*
24 | 24
*/
首先我们需要知道list是个什么东东:
点进std::list
template <class _Tp, class _Alloc /*= allocator<_Tp>*/>
class _LIBCPP_TEMPLATE_VIS list
: private __list_imp<_Tp, _Alloc>
{
...
}
点进__list_imp可以看到这个代码,有一个__end_,我们离真相又近了一点了,__end_是__node_base类型的,可以看到前边有个typedef:
template <class _Tp, class _Alloc>
class __list_imp
{
protected:
typedef _Tp value_type;
typedef typename __alloc_traits::void_pointer __void_pointer;
typedef __list_node_base<value_type, __void_pointer> __node_base;
__node_base __end_;
...
}
点进__list_node_base,看看这是个啥玩意。哦豁,发现了两个指针!
struct __list_node_base
{
typedef __list_node_pointer_traits<_Tp, _VoidPtr> _NodeTraits;
typedef typename _NodeTraits::__node_pointer __node_pointer;
typedef typename _NodeTraits::__base_pointer __base_pointer;
typedef typename _NodeTraits::__link_pointer __link_pointer;
__link_pointer __prev_;
__link_pointer __next_;
};
注意,这是个父结构体,再看看他子结构体的实现,如下:
template <class _Tp, class _VoidPtr>
struct __list_node
: public __list_node_base<_Tp, _VoidPtr>
{
_Tp __value_;
typedef __list_node_base<_Tp, _VoidPtr> __base;
typedef typename __base::__link_pointer __link_pointer;
_LIBCPP_INLINE_VISIBILITY
__link_pointer __as_link() {
return static_cast<__link_pointer>(__base::__self());
}
};
好啊,终于找到了list的数据成员了,两根指针,一个数据,类似于以下形式:
template<class T>
struct test {
T* prev;
T* next;
T t;
}
但是回到正题,为什么std::list
我的机子是64位机,指针是8bytes,int是4个字节,8*2+4 = 20,没毛病,20。
但是输出为什么是24呢?
遇到这种问题,我们一般就需要从编译器角度考虑了(首先可以肯定,这肯定不是我的问题!)
结构体对齐,嗯结构体对齐,这是编译器考虑的范畴。
内存对齐的作用:
字节对齐主要是为了提高内存的访问效率,比如intel 32位cpu,每个总线周期都是从偶地址开始读取32位的内存数据,如果数据存放地址不是从偶数开始,则可能出现需要两个总线周期才能读取到想要的数据,因此需要在内存中存放数据时进行对齐。
结论1:一般情况下,结构体所占的内存大小并非元素本身大小之和。
结论2:结构体内存大小应按最大元素大小对齐,如果最大元素大小超过模数,应按模数大小对齐。
这里的模数就需要编译器来操作啦!
我们试试取消内存对齐试试:
#include <list>
template<class T>
struct test {
T* prev;
T* next;
T t;
}__attribute__((__packed__)) ;
int main(){
printf("%d | %d \n", sizeof(int), sizeof(long long));
printf("%d | %d \n", sizeof(std::list<int>), sizeof(std::list<long long>));
printf("%d | %d \n", sizeof(test<int>), sizeof(test<long long>));
}
/*
4 | 8
24 | 24
20 | 24
*/
可以发现,test
内存对齐的相关知识可以参考:https://www.zhihu.com/question/27862634
详细的内存对齐内容,将在以后探讨....