今天通過這篇部落格,以兩個非常規視角介紹stl容器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之後兩個容器的內容發生了交換,而且!兩個容器的迭代器、指標、引用也會發生交換,a.swap(b)之後,a的迭代器依然有效,但是代表的元素位於b中。
#ifndef _common_h_
#define _common_h_
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace std;
#endif
//swap_op.cpp
#include
"common.h"
intmain
(void
)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
; vector<
int> int_vec1
; 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)
;return0;
}
編譯和執行結果
g++
-o swap_op swap_op.cpp -o0 -g -wall -std=c++11.
/swap_op
test_vec_shrink.
size()
:10test_vec_shrink.
capacity()
:16test_vec_swap.
size()
:10test_vec_swap.
capacity()
:16after shrink_to_fit:
test_vec_shrink.
size()
:10test_vec_shrink.
capacity()
:10after swap:
test_vec_swap.
size()
:10test_vec_swap.
capacity()
:10before swap, interator status:
it_int_vec0:
2it_int_vec1:
7after swap, interator status1:
it_int_vec0:
2it_int_vec1:
7after swap, interator status2:
it_int_vec0:
2it_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,這個特性其實有些危險,不熟悉的程式設計師容易不小心改錯值。
STL容器介紹
fighting進行時 2016.1.12 2016第一彈,明天考試 壓力賊大。廢話不多說了,今天學了stl裡的vector list set map。vector是乙個是個動態的陣列,相比陣列來講,有乙個好處 因為陣列呢,是一段連續的記憶體,如果說你要用10000個吧,但是你最開始只開了100個,...
STL容器介紹
stl的容器可以分為以下幾個大類 一 序列容器,有vector,list,deque,string.二 關聯容器,有set,multiset,map,mulmap,hash set,hash map,hash multiset,hash multimap 三 其他的雜項 stack,queue,va...
關於C 容器的swap操作
一 swap操作交換兩個相同型別的容器的內容,一般的容器 除array外 交換兩個容器內容的操作會保證非常快,因為並沒有交換元素本身,而只是交換了兩個容器的內部資料結構。拿vector做個例子 include include int main std vector ivec2 std cout st...