前几天在VS下测试得出的结论:
-
当数据量较小时,既可以使用vector(使用其push_back函数即可),也可以使用array或者内置数组,不过优先建议使用vector,其次是array,最后才是内置数组;
-
当数据量较大时,且不是全局变量或者静态变量时,此时由于array是在栈上分配空间,此时array不能用(因为栈空间有限,数据量太大就会栈溢出)(至少最新VS2019编译器是这样的),只能用vector或在堆上分配空间的内置数组(当然如果array是一个全局变量或者静态变量,那么它就是在全局静态区上,而不是在栈上了。更有甚者,如果array是类的成员,且此类的对象是new出来的,那么这个array也会分配到堆上)。此时:优先使用vector,且尽量预先分配空间,而不是用push_back()来添加数据。 因为数据量大时,push_back会很慢,如果预先知道数据量是多少,则在创建vector时就预先分配空间,然后存入数据时用下标来存入数据。使用最新VS2019编译器测试,在Release下,使用预分配的vector存入大量数据的速度比使用在堆上分配的内置数组存入数据要快很多;
-
在极少数极特殊情况下,使用内置类型数组(不管是堆上的还是栈上的)进行数据运算,会比使用下标的vector要快很多。比如
int size = 32768;
int* data = new int[size]; // 注意后面要释放内存
//std::vector<int> data(size);
for (int i = 0; i < size; ++i)
data[i] = rand() % 512;
long long sum = 0;
for (int i = 0; i < 1000; ++i) // 1
{
for (int index = 0; index < size; ++index)
{
if (data[index] > 256)
sum += data[index];
}
}
上述代码如果使用vector,在下面的双循环(即代码1处)的计算,要比使用内置数组慢很多倍。不过,经过测试,这种情况发生的前提是第一层循环的次数很多,此时两者才会有很大差异。如果第一层循环次数很少,即使第二层循环次数非常多(即元素数量非常大),那么这种情况下使用vector或者使用内置数组,它们消耗的时间没有什么差异,几乎相等。
话说回来,即使遇到上面这样的代码,也可以使用vector,通过一些小把戏,来达到与内置数组一样快的速度:
int size = 32768;
std::vector<int> data(size);
for (int i = 0; i < size; ++i)
data[i] = rand() % 512;
long long sum = 0;
int* rawDataMem = &data[0]; // 1 直接获取内部数组地址
for (int i = 0; i < 1000; ++i)
{
for (int index = 0; index < size; ++index)
{
if (rawDataMem[index] > 256) // 2
sum += rawDataMem[index]; // 3
}
}
如代码中1,2和3处所示,对于大小不变化的vector,其在内存中就是一个堆数组,所以我们可以在某些情况下绕过vector接口,而直接获取其内部数组中的元素,这样的写法等价是使用内置数组类型,且上述代码的执行时间与使用内置数组类型的代码相同。使用这种方式不需要主动管理内存,释放内存,很方便。
不过这种方式一般情况下不要使用,一般情况下直接用vector的接口并不比上述方法慢多少,且一旦vector中元素个数变化了,其指针就失效了,有点危险。因此,只有在这种极少数情况下可以尝试性地使用。
综上所述,当数据量小时,尽量使用vector及其push_back()成员函数来添加数据;当数据量很大时,尽量使用vector且预先分配好大小,添加数据时用下标添加。