swap之vector的特化

最近遇到了vector的swap的操作,此前对于该部分并没有了解过,此处主要是通过实验、阅读源码以及网上一些博客后进行总结

关于swap

此处写了个非常简单的demo

#include <iostream>
#include <vector>

using namespace std;

void printVec(const vector<int> &vec) {
    cout << "vector members: ";
    for(auto &num : vec) {
        cout << num << " ";
    }
    cout << endl;
}

int main() {
    vector<int> a = {1, 2, 3, 4, 5};
    vector<int> b;

    cout << "before swap: " << endl;
    cout << "a: ";
    printVec(a);
    cout << "b: ";
    printVec(b);

    a.swap(b);

    cout << "after swap: " << endl;
    cout << "a: ";
    printVec(a);
    cout << "b: ";
    printVec(b);

    return 0;
}

其输出结果相信也是比较直观的,就是交换了vector的内容

before swap:
a: vector members: 1 2 3 4 5
b: vector members:
after swap:
a: vector members:
b: vector members: 1 2 3 4 5

但是具体交换了什么呢?

此处可以查看起具体的实现源码

void swap(vector& _Right) noexcept // strengthened
    {	// exchange contents with _Right
    if (this != _STD addressof(_Right))
        {	// (maybe) swap allocators, swap control information
        _Pocs(this->_Getal(), _Right._Getal());
        this->_Swap_all(_Right);
        _Swap_adl(this->_Myfirst(), _Right._Myfirst());
        _Swap_adl(this->_Mylast(), _Right._Mylast());
        _Swap_adl(this->_Myend(), _Right._Myend());
        }
    }

同时在cpluscplus网站对此有介绍到

Swap content
Exchanges the content of the container by the content of x, which is another vector object of the same type. Sizes may differ.
After the call to this member function, the elements in this container are those which were in x before the call, and the elements of x are those which were in this. All iterators, references and pointers remain valid for the swapped objects.
Notice that a non-member function exists with the same name, swap, overloading that algorithm with an optimization that behaves like this member function.

在做swap的时候,不仅两个容器的内容被交换,同时他们的迭代器、指针和引用也将被交换。在swap发生后,原先指向某容器中元素的迭代器、指针和引用仍然有效,并且指向相同的元素,即swap操作前后迭代器不失效。

对于swap后关于迭代器部分可能过于绕口,此处提供简单的demo说明

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> v1 = {1, 3, 5};
    vector<int> v2 = {2, 4, 6};
    vector<int>::iterator it1 = v1.begin();
    vector<int>::iterator it2 = v2.begin();
    cout << "&v1[0]=" << &v1[0] << "\t\t"
         << "*it1=" << *it1 << endl;
    cout << "&v2[0]=" << &v2[0] << "\t\t"
         << "*it1=" << *it2 << endl;

    v1.swap(v2);

    cout << "after v1.swap(v2)" << endl;
    cout << "&v1[0]=" << &v1[0] << "\t\t"
         << "*it1=" << *it1 << endl;
    cout << "&v2[0]=" << &v2[0] << "\t\t"
         << "*it1=" << *it2 << endl;

    return 0;
}
&v1[0]=0x1c5e00         *it1=1
&v2[0]=0x1c5e20         *it1=2
after v1.swap(v2)
&v1[0]=0x1c5e20         *it1=1
&v2[0]=0x1c5e00         *it1=2

可以看出经过swap后迭代器仍然有效,但是此处如果在迭代器遍历访问的时候终止条件应当是swap的另一个容器的end了。

vector的swap妙用

  1. 释放vector多余的空间或者清空vector

vector可自动增大容量,但是其不会自动的缩减的。可能大家都会记得vector还有个clear函数,但是clear只是删除存储在vector中的所有元素,并不是释放了vector的内存,其引用、指针、迭代器也是继续有效。那么当在一个较大的vector中删除了大量的元素之后,其实际的size比较小,而其capacity比较大,如果对空间比较敏感,希望vector的容量能够缩小一些。这时可以使用swap的技巧来实现,通过swap一个空的或者容量较小的vector对象达到该目的。

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> v1 = {1, 3, 5};
    vector<int> v2;

    cout << "before" << endl;
    cout << "size: " << "v1.size = " << v1.size() << ", v2.size = " << v2.size() << endl;;
    cout << "capacity: " << "v1.capacity = " << v1.capacity() << ", v2.capacity = " << v2.capacity() << endl;

    v1.swap(v2);

    cout << "after" << endl;
    cout << "size: " << "v1.size = " << v1.size() << ", v2.size = " << v2.size() << endl;;
    cout << "capacity: " << "v1.capacity = " << v1.capacity() << ", v2.capacity = " << v2.capacity() << endl;

    return 0;
}
size: v1.size = 3, v2.size = 0
capacity: v1.capacity = 3, v2.capacity = 0
after
size: v1.size = 0, v2.size = 3
capacity: v1.capacity = 0, v2.capacity = 3

参考链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值