function template
C++98: <algorithm>, C++11: <utility>
std::swap
template <class T> void swap (T& a, T& b);
標頭檔案 | // moved from <algorithm> to <utility> in C++11 |
---|
非陣列 (1) | template <class T> void swap (T& a, T& b) noexcept (is_nothrow_move_constructible<T>::value && is_nothrow_move_assignable<T>::value); |
---|
陣列 (2) | template <class T, size_t N> void swap(T (&a)[N], T (&b)[N]) noexcept (noexcept(swap(*a,*b))); |
---|
交換兩個物件的數值
交換 a 和 b 的值。
此函式模板的行為等同於
1 2 3 4
|
template <class T> void swap ( T& a, T& b )
{
T c(a); a=b; b=c;
}
|
請注意,此函式涉及複製構造和兩次賦值操作,對於儲存大量資料的類的交換內容而言,這可能不是最高效的方式,因為這些操作中的每一個通常都與其大小成線性關係。
大型資料型別可以提供此函式的過載版本來最佳化其效能。特別是,所有
標準容器都對其進行了專門化處理,只交換少數內部指標,而不是其全部內容,使其操作時間為常數。
此函式不再定義在標頭檔案
<algorithm>
中,而是在
<utility>
中。
這些函式模板的行為等同於
1 2 3 4 5 6 7 8
|
template <class T> void swap (T& a, T& b)
{
T c(std::move(a)); a=std::move(b); b=std::move(c);
}
template <class T, size_t N> void swap (T (&a)[N], T (&b)[N])
{
for (size_t i = 0; i<N; ++i) swap (a[i],b[i]);
}
|
標準庫的許多元件(在 std 名稱空間內)會以 *未限定* 的方式呼叫 swap,以允許呼叫為非基本型別宣告的自定義過載,而不是此通用版本:在為某個型別宣告的相同名稱空間中宣告的 swap 的自定義過載,透過*依賴於引數的查詢*(argument-dependent lookup)而非此通用版本來選擇。
引數
- a, b
- 兩個物件,它們的 contents 被交換。
型別 T 必須是*可複製構造*(copy-constructible)且*可賦值*(assignable)的。
型別
T 必須是*可移動構造*(move-constructible)且*可移動賦值*(move-assignable)的(對於版本 (2),或者為其定義了
swap)。
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
// swap algorithm example (C++98)
#include <iostream> // std::cout
#include <algorithm> // std::swap
#include <vector> // std::vector
int main () {
int x=10, y=20; // x:10 y:20
std::swap(x,y); // x:20 y:10
std::vector<int> foo (4,x), bar (6,y); // foo:4x20 bar:6x10
std::swap(foo,bar); // foo:6x10 bar:4x20
std::cout << "foo contains:";
for (std::vector<int>::iterator it=foo.begin(); it!=foo.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
|
輸出
foo contains: 10 10 10 10 10 10
|
複雜度
非陣列:常數:執行一次構造和兩次賦值(儘管請注意,這些操作中的每一個都基於其自身複雜度)。
陣列:相對於 N 為線性:對每個元素執行一次交換操作。
異常
如果型別 T 的構造或賦值操作丟擲異常,則此函式也丟擲異常。
如果 T 是*無丟擲移動構造*(nothrow-move-constructible)且*無丟擲移動賦值*(nothrow-move-assignable)的,則此函式永不丟擲異常。
請注意,如果 T 不滿足上面(在 parameters 中)指定的要求,則會導致*未定義行為*(undefined behavior)。