std::
swap
公众成员函数 C++98<algorithm>,C++11<utility>
C++98 |
template <class T> void swap (T& a, T& b); |
C++11 |
header |
// moved from <algorithm> to <utility> in C++11 |
|
non-array (1) |
template <class T> void swap (T& a, T& b)
noexcept (is_nothrow_move_constructible<T>::value && is_nothrow_move_assignable<T>::value); |
|
array (2) |
template <class T, size_t N> void swap(T (&a)[N], T (&b)[N])
noexcept (noexcept(swap(*a,*b))); |
交换两个对象的值
交换a和b的值。
-
C++98:
-
这个函数模板的行为相当于:
template <class T> void swap ( T& a, T& b )
{
T c(a); a=b; b=c;
} |
请注意,这个函数涉及一个复制构造和两个赋值操作,
这可能不是交换存储大量数据的类内容的最有效方式,
因为每个操作通常在线性时间内对其大小进行操作。
大型数据类型可以提供此函数的重载版本,以优化其性能。
值得注意的是,所有标准容器都这样专门化它,即只交换少数内部指针,
而不是交换它们的全部内容,从而使它们在常量时间内操作。
-
C++11:
-
这个函数不再定义在头文件<algorithm>中,而是定义在<utility>中。
这些函数模板的行为相当于:
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,以允许调用非基本类型的自定义重载,
而不是这个泛型版本:在与所提供的类型相同的命名空间中声明的交换的自定义重载,
通过对该泛型版本的依赖参数查找来选择。
☲ 参数
-
a, b
-
两个对象,其内容被交换。
C++98: T型应是可复制构造和可转移的。
C++11: 类型T应该是可移动构造和可移动赋值的(或者在版本(2)中为它定义了swap)。
-
☉ 返回值
none
☣ 示例
// 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
✥ 复杂度
Non-array: Constant:只执行一个构造和两个赋值操作(不过请注意,每个操作都取决于其自身的复杂性)。
Array: Linear in N:对每个元素执行交换操作。
⇄ 数据竞争
a和b都被修改
☂ 异常安全性
如果类型T的构造或赋值抛出,则抛出。
如果T是nothrow-move-constructible和nothrow-move-assignable,则永不抛出。
注意,如果T没有满足上面指定的要求(在参数中),它将导致未定义的行为。
🍄 另请参阅
copy |
复制范围的元素(公众成员函数) |
fill |
用值填充范围(公众成员函数) |
replace |
复制并比较替换范围内的值(公众成员函数) |