1、容器的capacity、max_size以及内存分配
capacity - 容器的成员函数capacity()取得
max_size - 容器的成员函数max_size()取得
STL容器的capacity属性,表示STL在发生realloc前能允许的最大元素数,也可以理解为预分配的内存空间。例如一个vector<int> v的capacity为5,当插入第6个元素时,vector会realloc,vector内部数据会复制到另外一个内存区域。这样之前指向vector中的元素的指针、迭代器等等均会失效。
max_size属性和capacity不同,表示STL容器允许的最大元素数,通常,这个数是一个很大的常整数,可以理解为无穷大。这个数目与平台和实现相关,在我的机器上vector<int>的max_size为1073741823,而string的max_size为4294967294。因为max_size很大~所以基本不会发生元素数超过max_size的情况。
2、设定capacity
List, Map/Multimap, Set/Multiset, Deque
并不是所有的容器都会发生realloc,List,Map/Multimap,Set/Multiset的元素在内存中散布,不预分配内存,所以不会产生realloc的情况,对于这些容器,其capacity是无意义的,所以这些容器没有capacity()成员函数,也没有capacity属性。
deque双向队列情况比较特殊,deque将内存分块,每次分配固定大小的分块,一个分块填充满后开辟新的分块,也属于散布-连续混杂的情况,虽然deque会预分配内存空间,但也不会产生realloc(人家是alloc),所以也不具有capacity属性。
Vector, String, basic_string<wchar_t>
实际具有capacity属性的容器只有vector和string,在不同实现下,capacity也不尽相同。在我的机器上,情况如下:
vector<T>
默认构造函数 - capacity = 0
使用构造函数vector<T>(n, value=T())指定capacity - capacity = n
string (basic_string<char> )
默认构造函数 - capacity = 15
没有指定capacity的构造式
指定了初始字符串的 - capacity = 大于字符串长度且等于n*15-1
basic_string<wchar_t>
默认构造函数 - capacity = 7
指定了初始字符串的 - capacity = 大于字符串长度且等于n*8-1
3、内存分配情况:
当使用push_back和insert插入元素时,如果当前元素数(用size()求得)超过了当前容量(capacity()求得),则需要重新寻找一块能够容纳当前元素的连续内存空间,然后,将原来的元素插入到这个新空间中,最后释放原来的内存空间。由于频繁的realloc和free空间很浪费时间,所以,当realloc时,重新申请的空间一般要大于当前所需,不同的开发环境申请的空间大小不同。
codeblocks中vector的扩充机制:按照容器现在容量的一倍进行增长。 vector容器分配的是一块连续的内存空间,每次容器的增长,并不是在原有连续的内存空间后再进行简单的叠加, 而是重新申请一块更大的新内存,并把现有容器中的元素逐个复制过去,然后销毁旧的内存。 这时原有指向旧内存空间的迭代器已经失效,所以当操作容器时,迭代器要及时更新
vs2010中的扩容机制:1,2,3,4,6,9,13,19,28,42,63.。。。。
capacity只增不减!