C++ vector容器-45-vector互换和节省空间和预留空间
这篇来学习vector一个互换操作,也就是有两个vector对象,可以通过一个api,把两个对象互换过来。实际上,就是在内存中交换了对象的指针,原来的指针指向新的vector对象。这种交换有时候是很有必要,特别是匿名vector对象进行交换后可以节约内存空间,最后来看看vector的预留空间相关的知识点。1.两个vector互换互换的函数很简单swap(vect),当前容器和传进来的vect容器进
这篇来学习vector一个互换操作,也就是有两个vector对象,可以通过一个api,把两个对象互换过来。实际上,就是在内存中交换了对象的指针,原来的指针指向新的vector对象。这种交换有时候是很有必要,特别是匿名vector对象进行交换后可以节约内存空间,最后来看看vector的预留空间相关的知识点。
1.两个vector互换
互换的函数很简单swap(vect),当前容器和传进来的vect容器进行交换。下面代码先创建两个vector对象,然后进行打印交换前和交换后的容器元素。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void printVector(vector<int> &v)
{
// for循环迭代器遍历容器内元素
for(vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
// vector互换
vector<int> vec;
// 1 尾部插入元素
vec.push_back(2);
vec.push_back(4);
vec.push_back(6);
vec.push_back(8);
vec.push_back(10);
vector<int> vec2;
for(int i=10; i>0; i--)
{
vec2.push_back(i);
}
cout << "before swap:" << endl;
printVector(vec);
printVector(vec2);
cout << "after swap:" << endl;
vec.swap(vec2);
printVector(vec);
printVector(vec2);
}
int main()
{
test01();
system("pause");
return 0;
}
运行结果:
举例容器size变小,容量就没有相应变小
有时候一开始我们创建的vector容器的capacity会很大,然后后面代码通过resize函数,使容器元素个数变小,但是容量还是很大,这样就浪费内存空间,看看下面这个例子。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void printVector(vector<int> &v)
{
// for循环迭代器遍历容器内元素
for(vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vector<int> vec;
for(int i=0; i<100000; i++)
{
vec.push_back(i);
}
cout << "capacity:" << vec.capacity() << endl;
cout << "size:" << vec.size() << endl;
vec.resize(3);
cout << "capacity:" << vec.capacity() << endl;
cout << "size:" << vec.size() << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
结果
在28行代码之后,我们可能只需要存储3个元素,但是这个容器的容量还是初始的时候13万多大小,这个内存空间是无法自动回收,很是浪费内存空间。
2.匿名vector对象进行互换后节省内存空间
针对上面这种浪费内存空间的场景,我们可以通过匿名对象调用swap方法来解决。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void printVector(vector<int> &v)
{
// for循环迭代器遍历容器内元素
for(vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vector<int> vec;
for(int i=0; i<100000; i++)
{
vec.push_back(i);
}
cout << "capacity:" << vec.capacity() << endl;
cout << "size:" << vec.size() << endl;
vec.resize(3);
vector<int>(vec).swap(vec);
cout << "capacity:" << vec.capacity() << endl;
cout << "size:" << vec.size() << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
就增加第29行代码
第29行代码vector<int>(vec),这个部分是一个匿名对象,根据vec的长度,这里就是3去构造一个新的vector<int>对象,这个对象就是一个匿名对象,然后调用swap函数,把vec容器的容量也减少到3. 这个匿名对象只在29行有效,29行结束的时候会自动会编译器回收内存,这个是匿名对象的特点。
3.预留空间
下面看看一个vector容器如果要插入10万个数,在g++编译环境下需要动态扩展容器容量多少次才能解决存储10万个数元素
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void printVector(vector<int> &v)
{
// for循环迭代器遍历容器内元素
for(vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vector<int> vec;
int num = 0; // 统计内存开辟次数
int *p = NULL;
for(int i=0; i<100000; i++)
{
vec.push_back(i);
if(p != &vec[0])
{
p = &vec[0];
num++;
}
}
cout << "num:" << num << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
上面这个指针p,一开始是NULL, 我们知道在内存中,数组或者字符串的指针都是默认指向数组第一个元素的位置。这个p就是通过这个特点来统计,只要扩容一次,数组首地址就发生变化一次,这样统计扩容次数的。
我这里是18次出现扩容,如果在vs上可能是30次左右。也就是发生18次动态扩容才搞定这个容器存储10万个数。如果我们一开始就大概知道这个容器需要多少空间,我们可以通过预留空间的办法去减少容器动态扩容的次数。
在vector容器中,预留空间使用reserve(int n)。
reserve(int len); //容器预留len个元素长度,预留位置不初始化,元素不可以访问
这个预留空间的作用是减少vector在动态扩展容量时的扩展次数,看下面代码
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void printVector(vector<int> &v)
{
// for循环迭代器遍历容器内元素
for(vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vector<int> vec;
vec.reserve(100000);
int num = 0; // 统计内存开辟次数
int *p = NULL;
for(int i=0; i<100000; i++)
{
vec.push_back(i);
if(p != &vec[0])
{
p = &vec[0];
num++;
}
}
cout << "num:" << num << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
这样一次就搞定,节约动态扩容的时间。
更多推荐
所有评论(0)