目的

此文旨在弄清c++中vector的三个成员函数size(), capacity(), max_size()的返回值的意义和关系。其函数原型分别如下:

size_type size() const;
size_type capacity() const
size_type max_size() const;

测试代码

下边这段代码唯一做的事情就是建立一个vector,并不停的往里加数据,每当capacity改变时,将size(), capacity(), max_size()三个函数的返回值分别打印出来:

#include <stdio.h>
#include <vector>
int main() {
	std::vector<double> v;
	printf("size:%d capacity:%d max_size:%llu\n",v.size(),v.capacity(),v.max_size());
	int last_capacity = -1;
	for (int i = 0; i < v.max_size(); ++i) {
		v.push_back(1.0*i);
		if (last_capacity!=v.capacity()) {
			printf("size:%10d capacity:%10d c/l:%d max_size:%llu\n",
				v.size(),v.capacity(),v.capacity()/last_capacity,v.max_size());
		}
		last_capacity = v.capacity();
	}
	return 0;
}

代码输出如下:
这里写图片描述
这里写图片描述

不同编译器下的结果

上边测试结果在visual studio下跑出(具体哪个版本忘记了,抱歉,不过这不是重点),下边是visual studio 2019和Ubuntu g++下的测试结果,重点关注capacity(), max_size()的返回值。
在这里插入图片描述

结论

从以上输出中我们可以得到以下几个结论:

  1. vector的最大容量max_size是2305843009213693951,这个值不变,这个“最大”只是逻辑上的,也就是这个类型逻辑上支持vector的最大长度,即capacity()重新分配的上限。

程序持续运行下去,直到重新向操作系统申请内存时会报错,max_size是2305843009213693951这个说法其实不确切,只能说明其是一个定值,具体大小由编译器决定。

  1. vector的capacity,是指当前状态下(未重新向操作系统申请内存前)的最大容量。这个值如果不指定,则开始是0,加入第一个值时,由于capacity不够,向操作系统申请了长度为1的内存。在这之后每次capacity不足时,都会重新向操作系统申请长度为原来两倍的内存。

由此也可以得出结论,最佳方法是vector创建时,就指定一个capacity,无法预知大小没关系,先设一个值,总比0好。这样避免频繁的realloc操作,提高程序效率。

  1. 另外,重新申请内存的策略由编译器决定。从上节的结果我们可以看出,g++编译器使用的是两倍策略。而visual studio 2019则使用的是1.5 倍策略(这个方法更优秀!)。

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\include\vector

    size_type _Calculate_growth(const size_type _Newsize) const {
       // given _Oldcapacity and _Newsize, calculate geometric growth
       const size_type _Oldcapacity = capacity();

       if (_Oldcapacity > max_size() - _Oldcapacity / 2) {
           return _Newsize; // geometric growth would overflow
       }

       const size_type _Geometric = _Oldcapacity + _Oldcapacity / 2;

       if (_Geometric < _Newsize) {
           return _Newsize; // geometric growth would be insufficient
       }

       return _Geometric; // geometric growth is sufficient
   }
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐