函式模板
C++98: <algorithm>, C++11: <utility>
std::swap
// defined in <algorithm> before C++11template <class T> void swap (T& a, T& b);
非陣列 (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 的值。
在 C++11 之前,此函式定義在標頭檔案
<algorithm>
中。
此函式模板的行為等同於
1 2 3 4
|
template <class T> void swap ( T& a, T& b )
{
T c(a); a=b; b=c;
}
|
請注意,此函式涉及複製構造和兩次賦值操作,對於儲存大量資料的類,這可能不是交換其內容的最有效方法,因為每次操作的時間複雜度都與其大小成線性關係。
大型資料型別可以提供此函式的過載版本來最佳化其效能。特別是,所有
標準容器 都會對其進行特化,只交換少量內部指標而不是其全部內容,從而使其操作時間複雜度為常數。
這些函式模板的行為等同於
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 自定義過載版本,透過 *依賴於引數的查詢* 選擇,而不是此通用版本。
引數
- a, b
- 兩個物件,它們的數值被交換。
型別 T 必須是 *可複製構造* 且 *可賦值*。
型別
T 必須是 *可移動構造* 且 *可移動賦值*(或為其定義了
swap,對應版本 *(2)*)。
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
// swap algorithm example (C++11)
#include <iostream> // std::cout
#include <utility> // std::swap
int main () {
int x=10, y=20; // x:10 y:20
std::swap(x,y); // x:20 y:10
int foo[4]; // foo: ? ? ? ?
int bar[] = {10,20,30,40}; // foo: ? ? ? ? bar: 10 20 30 40
std::swap(foo,bar); // foo: 10 20 30 40 bar: ? ? ? ?
std::cout << "foo contains:";
for (int i: foo) std::cout << ' ' << i;
std::cout << '\n';
return 0;
}
|
輸出
foo contains: 10 20 30 40
|
複雜度
非陣列: 常數:執行一次構造和兩次賦值(儘管請注意,每次操作都根據其自身複雜度進行)。
陣列: 線性於 N:對每個元素執行一次交換操作。
異常
如果型別 T 的構造或賦值操作丟擲異常,則此函式丟擲異常。
如果 T 是 *無異常移動構造* 且 *無異常移動賦值*,則永遠不會丟擲異常。
請注意,如果 T 不滿足上述要求(在 parameters 中指定),將導致 *未定義行為*。