C++ vector容器 动态数组 常用 API 操作

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 收缩内存空间

C++ vector容器的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;//这种写法把迭代器当作指针使用了,虽然这里可以,但迭代器毕竟不是指针,复杂的地方会出错
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

R-G-B

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值