STL容器swap操作介绍

readme

今天通过这篇博客,以两个非常规视角介绍STL容器swap操作。swap操作非常容易理解,因为字面意思不多不少的表达了函数所做的事,也即“交换”,关于swap做了什么唯一值得关注的就是交换的是指针而非内容。那么交换之后容器的状态呢,是否可以通过交换达到其他什么目的呢。

通过swap缩容

常见的连续内存容器,例如vector,string,存储元素的数量和容量是两个不同的概念,而且大多数时候容量都大于数量。这是改善效率的一种做法,避免频繁分配释放内存。
用户可以通过clear()清空容器,但clear()不会释放容量。用户可以通过shrink_to_fit()释放容量至尽可能小,具体有多小呢,不同的实现有不同的结果。
重点来了!用户还可以通过神奇的swap操作达到相同的目的,而且更通用更可靠,不会因为不同的STL底层实现得到不同的结果。网传一种神奇的vector().swap(test_vec)操作可以释放test_vec占用的内存,虽然释放内存并不靠谱儿(之前有一片博客“如何主动释放c++程序中STL容器不愿自动释放的内存”介绍过一种更靠谱儿的方式)但是确实可以清空test_vec,可以清空元素,清空容量。swap也能达到shrink_to_fit()的目的。如果不希望清空,仅仅希望让容量尽可能小,也是有办法的,下文程序中有介绍。

swap之后

swap之后两个容器的内容发生了交换,而且!两个容器的迭代器、指针、引用也会发生交换,a.swap(b)之后,a的迭代器依然有效,但是代表的元素位于b中。

测试程序

//common.h
#ifndef _COMMON_H_
#define _COMMON_H_

#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <utility>
#include <algorithm>
#include <vector>
#include <iterator>
#include <sys/time.h>

using namespace std;
#endif
//swap_op.cpp
#include "common.h"

int main(void)
{
    vector<int> test_vec_shrink;
    vector<int> test_vec_swap;
    for (int i = 0; i < 10; ++i)
    {
        test_vec_shrink.push_back(i);
        test_vec_swap.push_back(i);
    }
    printf("test_vec_shrink.size(): %lu\n", test_vec_shrink.size());
    printf("test_vec_shrink.capacity(): %lu\n", test_vec_shrink.capacity());
    printf("test_vec_swap.size(): %lu\n", test_vec_swap.size());
    printf("test_vec_swap.capacity(): %lu\n", test_vec_swap.capacity());

    test_vec_shrink.shrink_to_fit();
    printf("after shrink_to_fit:\ntest_vec_shrink.size(): %lu\n", test_vec_shrink.size());
    printf("test_vec_shrink.capacity(): %lu\n", test_vec_shrink.capacity());

    vector<int>(test_vec_swap).swap(test_vec_swap);
    printf("after swap: \ntest_vec_swap.size(): %lu\n", test_vec_swap.size());
    printf("test_vec_swap.capacity(): %lu\n", test_vec_swap.capacity());

    vector<int> int_vec0{0, 1, 2, 3, 4};
    vector<int> int_vec1{5, 6, 7, 8, 9};
    vector<int>::iterator it_int_vec0 = int_vec0.begin();
    vector<int>::iterator it_int_vec1 = int_vec1.begin();
    it_int_vec0 = it_int_vec0 + 2;
    it_int_vec1 = it_int_vec1 + 2;
    printf("before swap, interator status:\nit_int_vec0: %d\nit_int_vec1: %d\n", *it_int_vec0, *it_int_vec1);

    int_vec0.swap(int_vec1);
    printf("after swap, interator status1:\nit_int_vec0: %d\nit_int_vec1: %d\n", *it_int_vec0, *it_int_vec1);

    int_vec0[2] = 999;
    printf("after swap, interator status2:\nit_int_vec0: %d\nit_int_vec1: %d\n", *it_int_vec0, *it_int_vec1);

    return 0;
}

编译和执行结果

g++ -o swap_op swap_op.cpp -O0 -g -Wall -std=c++11
./swap_op 
test_vec_shrink.size(): 10
test_vec_shrink.capacity(): 16
test_vec_swap.size(): 10
test_vec_swap.capacity(): 16
after shrink_to_fit:
test_vec_shrink.size(): 10
test_vec_shrink.capacity(): 10
after swap: 
test_vec_swap.size(): 10
test_vec_swap.capacity(): 10
before swap, interator status:
it_int_vec0: 2
it_int_vec1: 7
after swap, interator status1:
it_int_vec0: 2
it_int_vec1: 7
after swap, interator status2:
it_int_vec0: 2
it_int_vec1: 999

测试程序解释

测试程序中vector(test_vec_swap).swap(test_vec_swap);可以理解为做了这几件事:通过vector拷贝构造函数创建一个test_vec_swap复本,但是仅仅复制元素,不会复制多余的容量,之后用这个复本和原来的test_vec_swap所swap操作,操作的结果就是仅仅留下元素,不会有多余的容量。
如果将vector(test_vec_swap).swap(test_vec_swap);替换成vector().swap(test_vec_swap);,就会新建一个空vecotr,然后和目标做swap操作,结果就是只剩一个空vector,没有元素,没有容量。
如果两个容器做swap之后,例如测试程序中int_vec0和int_vec1,swap之前它们的迭代器it_int_vec0和it_int_vec1,swap之后依然有效,但是代表的元素交换了位置,例如int_vec0[2] = 999;之后,it_int_vec1的值变成了999,这个特性其实有些危险,不熟悉的程序员容易不小心改错值。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值