函式模板
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)));
交換兩個物件的數值
交換 ab 的值。

在 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:對每個元素執行一次交換操作。

資料競爭

ab 都會被修改。

異常

如果型別 T 的構造或賦值操作丟擲異常,則此函式丟擲異常。
如果 T 是 *無異常移動構造* 且 *無異常移動賦值*,則永遠不會丟擲異常。
請注意,如果 T 不滿足上述要求(在 parameters 中指定),將導致 *未定義行為*。

另見