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)。