vector容器成员函数——reserve()及迭代器失效问题

一、vector容器成员函数——reserve()

2.实用意义:

vecotr容器中不断的push_back(), 会进行多次内存再分配行为,为了减少内存再分配的次数,下面有请reserve()函数出场!!!

3.功能:

增加vector容器容量 c a p a c i t y capacity capacity

4.使用方法

函数原型:

void reserve( size_type new_cap );

参数介绍:

new_cap:vector的新容量

5.例子

  • 5.1 结论reserve()不改变vector的大小 s i z e size size,改变vector的容量 c a p a c i t y capacity capacity,以下是证明:
int foo()
{
    vector<int> v{ 1, 3, 5, 7, 9 };
    cout << v.size() << endl;		// 5
    cout << v.capacity() << endl;	// 5
    
    v.reserve(10);	// (1) 改变vector的什么呢?
    cout << "After reserve(): " << endl;	

    cout << v.size() << endl;		// 5,看!不改变vector的元素个数
    cout << v.capacity() << endl;	// 10,改变了vector的容量!

    return 0;
}
  • 5.2 结论reserve(new_cap),当new_cap大于vector原本的容量时,迭代器会失效!!

    当要新容量大于vector原本的容量时,vector会找一个更大的空间,然后vector中的所有元素将会拷贝到这个更大的新空间里,这时所有迭代器将会失效。为什么会失效?

    因为迭代器也是一个指针,它指向的是过去分配的存储空间,当vector元素搬家后,而迭代器仍指向旧的家的存储单元。

    以下是证明:

    void test5_2(vector<int>& v)	//capacity为 5
    {
        vector<int>::iterator iter = v.begin();
        for (;iter != v.end(); ++iter)
            cout << *iter << " ";	// 1, 3, 5, 7, 9
        cout << endl;
    
        v.reserve(10);
    
        for (;iter != v.end(); ++iter)
            cout << *iter << " ";	// 一堆随机数
        cout << endl;
        return ;
    }
    

    下面输出的第一行是调用reserve()之前,通过迭代器正常输出的vector元素; 在这里插入图片描述

    那如何处理迭代器失效呢?其实再给迭代器赋值一次v.begin()就好辣!

    void test5_2(vector<int>& v)
    {
        vector<int>::iterator iter = v.begin();
        for (;iter != v.end(); ++iter)
            cout << *iter << " ";
        cout << endl;
    
        v.reserve(10);
    	iter = v.begin();	// 就看这一行!!!,比上面代码就多了这一句
        for (;iter != v.end(); ++iter)
            cout << *iter << " ";	
        cout << endl;
        return ;
    }
    

    聪明的你一定早就知道方法啦,还是看一下输出吧:

    1 3 5 7 9
    1 3 5 7 9
    

    这下迭代器就没事啦!

    到这里一定很好奇,如果reserve(new_cap)中的new_cap小于vector原本的容量,那将会怎么样?

    测试结论是没有任何效果,所以还是安安分分使用reserve()作为vector扩容的方法吧,如果需要缩小vector容量,可以使用shrink_to_fit()

    测试证明:

    void test5_1(vector<int>& v)
    {
        cout << v.size() << endl;		// 5
        cout << v.capacity() << endl;	// 5
    
        v.reserve(8);
        cout << "After reserve(8): " << endl;
    
        cout << v.size() << endl;		// 5
        cout << v.capacity() << endl;	// 8,不出预料变8了	
    	
        v.reserve(3);	// 我缩!!
        cout << v.size() << endl;   	// 5
        cout << v.capacity() << endl;	// 8,没有起任何效果
        return ;
    }
    

6.注意

  1. 正确使用reserve可以避免不必要的内存再分配,例如,未初始化的vector变量v1,如果多次进行push_back()操作,必然会有多次内存再分配的操作。如果在push_back()之前使用reserve进行一次合理的扩容,那就会提高性能。
  2. 当vector按引用传递给函数作参数时,如果不知道该vector的使用特征,还是不要使用reserve()为好。

来源:cppreference注意事项

Correctly using reserve() can prevent unnecessary reallocations, but inappropriate uses of reserve() (for instance, calling it before every push_back() call) may actually increase the number of reallocations (by causing the capacity to grow linearly rather than exponentially) and result in increased computational complexity and decreased performance. For example, a function that receives an arbitrary vector by reference and appends elements to it should usually not call reserve() on the vector, since it does not know of the vector’s usage characteristics.

When inserting a range, the range version of insert() is generally preferable as it preserves the correct capacity growth behavior, unlike reserve() followed by a series of push_back()s.

reserve() cannot be used to reduce the capacity of the container; to that end shrink_to_fit() is provided.

最后,如果有误,烦请各位指出!!

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值