1 空间满了之后,自动开辟
vector未雨绸缪机制,满了之后,会自动了扩充为原来的2倍
(提高效率,避免频繁”配置新空间-数据移动-释放旧空间”)
作者在qt上运行的,我在VS上运行,中止“vector迭代器不兼容”
int main() {
vector<int> v;//最初容器没有元素,容量为空
cout << "容量" << v.capacity() << endl;
vector<int>::iterator it ;
int i = 0;
int count = 0;
for ( i = 0; i < 1000; i++) {
v.push_back(i);//插入第一个元素,开辟1空间;插入第二个元素,开辟2空间;插入第三个元素,开辟4空间。。。每次二倍
if (it != v.begin()) { //如果不相等,说明又开辟了新空间,v.begin指向新空间的开头;
count++;
cout <<"开辟空间容量: " << v.capacity() << endl;
it = v.begin();//it记录当前空间的开头
}
}
return 0;
}
2 事先预留空间
reserve(int len);//容器预留 len 个元素长度,预留位置不初始化,元素不可访问。
3 vector 大小操作
size();//返回容器中元素的个数
empty();//判断容器是否为空
resize(int num);//重新指定容器的长度为 num,若容器变长,则以默认值填充新位置。如果容器变短, 则末尾超出容器长度的元素被删除。
resize(int num, elem);//重新指定容器的长度为 num,若容器变长,则以 elem 值填充新位置。如果 容器变短,则末尾超出容器长>度的元素被删除。
capacity();//容器的容量
reserve(int len);//容器预留 len 个元素长度,预留位置不初始化,元素不可访问。
4 常用赋值操作
void printVectorInt(vector<int>& v) {
vector<int>::iterator it = v.begin();
for (; it != v.end(); it++)
cout << *it << " ";//看着像指针,其实不是指针
cout << endl;
}
void test2() {
vector<int> v1(5,100);//构造函数将 n 个 elem 拷贝给本身。
printVectorInt(v1);
vector<int> v2(v1.begin(),v1.end());
printVectorInt(v2);
vector<int> v3 = v1;
printVectorInt(v3);
vector<int> v4(v1);
printVectorInt(v4);
vector<int> v5;
v5.assign(v1.begin(), v1.end());//将[beg, end)区间中的数据拷贝赋值给本身
printVectorInt(v5);
}
5 容器互换 swap(vec)
swap(vec);// 将 vec 与本身的元素互换。
void test3() {
vector v6 = { 1,2,3,4,5,6 };
vector v7 = { 10,12 };
printVectorInt(v6);
printVectorInt(v7);
//v6,v7交换
v6.swap(v7); //同 swap(v6,v7);
printVectorInt(v6);
printVectorInt(v7);
}
6 巧用 swap 收缩内存空间
假如预留了一个较大空间,但实际上只用了很少一部分,现在想释放多余空间。
当我们将一个容量为一百万的容器,使用 resize(5) 函数重新指定大小为5的时候,它并不是向上图一样,就剩下5个空间,将其余空间释放掉,而是下图这种状态:
resize()做的操作大概是直接修改了数据量 大小,让我不能访问后面的数据,而容量还是100万。
这就是问题所在,重新指定大小后,这么大的空间就浪费掉了。
而swap()可以解决这个问题。
用法如下:
vector<int>(v).swap(v); //v是容器名
也就是说通过该语句,可以将v中空闲的空间释放掉。
这条语句可以分为两个部分:
vector(v) 和 .swap(v) 两部分
首先看第一部分,vector(v)
首先,这条语句,通过 拷贝构造函数 创建了一个 匿名对象 ,这个匿名对象拥有v的全部数据,但是,没有空闲的空间,也就是说,这个匿名对象的 容量 和 数据量 是相等的。如下图:
void test4() {
vector<int> v1;
v1.reserve(1000);
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
cout << "v1的容量:" << v1.capacity() << endl;
cout << "v1的大小:" << v1.size() << endl;
v1.resize(3);//resize只能修改大小 不能修改容量
cout << "v1.resize后的容量:" << v1.capacity() << endl;
cout << "v1.resize后的大小:" << v1.size() << endl;
vector<int>v2(v1);
cout << "v2的容量:" << v2.capacity() << endl;
cout << "v2的大小:" << v2.size() << endl;
}
所以经过 vector(v) 创建出来的匿名对象是没有空闲空间的,此时,通过 .swap(v) 调用该匿名类的swap()方法,交换v与匿名类的内容,结果如下:
最后,该行语句指向完毕,匿名类被析构,空间被释放。
最终结果就是,原容器中的空位被释放
void test5() {
vector<int> v1;
v1.reserve(1000000);//注意:是预留reserve,不是重置 resize
for (int i = 0; i < 5; i++)
{
v1.push_back(i);
}
cout << "v1的容量:" << v1.capacity() << endl;
cout << "v1的大小:" << v1.size() << endl;
vector<int>(v1).swap(v1); //不能写成v1.swap(v1);//v1自己与自己交换,结果没变化
cout << "\nswap释放空间后,v1的容量和大小:" << endl;
cout << "v1的容量:" << v1.capacity() << endl;
cout << "v1的大小:" << v1.size() << endl;
}
7 自定义数据类型(存放、遍历、排序)
//vector存放自定义数据类型
class Person
{
public:
friend void printVectorPerson(vector<Person>& v);//m_Name、m_Age是私有属性,要有元
friend bool compare(Person ob1, Person ob2);
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
private:
string m_Name;
int m_Age;
};
遍历容器中的数据
对象成员m_Name、m_Age是私有属性,故要在public定义有元之后,才可以使用
public:
friend void printVectorPerson(vector& v);
friend bool compare(Person ob1, Person ob2);
//遍历容器中的数据
void printVectorPerson(vector<Person>& v) {
vector<Person>::iterator it = v.begin();
for (; it != v.end(); it++)
// *it == Person
cout << "姓名:" << (*it).m_Name << " 年龄: " << (*it).m_Age << endl;//这两种输出都可以,但建议使用这种;
//cout << "姓名:" << it->m_Name << " 年龄:" << it->m_Age << endl;//这种写法把迭代器当作指针使用了,虽然这里可以,但迭代器毕竟不是指针,复杂的地方会出错
cout << endl;
}
//排序比较方式
ob1,ob2对象成员m_Name、m_Age是私有属性,故要在public定义有元之后,才可以使用
public:
friend void printVectorPerson(vector& v);
friend bool compare(Person ob1, Person ob2);
bool compare(Person ob1, Person ob2) {
return ob1.m_Age < ob2.m_Age;//按年龄升序
}
//排序,compare是排序方式,定义在上面
sort(v.begin(),v.end(),compare);
测试调用
void test6()
{
//创建一个vector容器,(数组)
vector<Person> v;
Person p1("a", 50);
Person p2("b", 20);
//向容器中插入数据
v.push_back(p1);
v.push_back(p2);
//向容器中插入数据
v.push_back(Person("c", 30));
v.push_back(Person("d", 40));
//遍历容器中的数据
printVectorPerson(v);
//排序,compare是排序方式,定义在上面
sort(v.begin(),v.end(),compare);
//遍历容器中的数据
printVectorPerson(v);
}
下面是容器中的数据打印输出,及按照年龄排序后打印输出
7 迭代器注意事项
vector::iterator it = v.begin();
// *it == Person
这里*it等价Person
以下两种输出都可以,但建议使用第一种;
第二种写法把迭代器当作指针使用了,虽然这里可以,但迭代器毕竟不是指针,复杂的地方会出错;
cout << "姓名:" << (*it).m_Name << " 年龄: " << (*it).m_Age << endl;//这两种输出都可以,但建议使用这种;
//cout << "姓名:" << it->m_Name << " 年龄:" << it->m_Age << endl;//这种写法把迭代器当作指针使用了,虽然这里可以,但迭代器毕竟不是指针,复杂的地方会出错