std::swap

来自cppreference.com
< cpp‎ | algorithm
 
 
算法库
受约束算法及范围上的算法 (C++20)
受约束算法: std::ranges::copy, std::ranges::sort, ...
执行策略 (C++17)
不修改序列的操作
(C++11)(C++11)(C++11)
(C++17)
修改序列的操作
Partitioning operations
划分操作
排序操作
(C++11)
二分搜索操作
集合操作(在已排序范围上)
堆操作
(C++11)
最小/最大操作
(C++11)
(C++17)

排列
数值运算
未初始化存储上的操作
(C++17)
(C++17)
(C++17)
C 库
 
在标头 <algorithm> 定义
(C++11 前)
在标头 <utility> 定义
(C++11 起)
在标头 <string_view> 定义
(C++17 起)
(1)
template< class T >
void swap( T& a, T& b );
(C++11 前)
template< class T >
void swap( T& a, T& b ) noexcept(/* 见下文 */);
(C++11 起)
(C++20 前)
template< class T >
constexpr void swap( T& a, T& b ) noexcept(/* 见下文 */);
(C++20 起)
(2)
template< class T2, std::size_t N >
void swap( T2 (&a)[N], T2 (&b)[N] );
(C++11 前)
template< class T2, std::size_t N >
void swap( T2 (&a)[N], T2 (&b)[N] ) noexcept(/* 见下文 */);
(C++11 起)
(C++20 前)
template< class T2, std::size_t N >
constexpr void swap( T2 (&a)[N], T2 (&b)[N] ) noexcept(/* 见下文 */);
(C++20 起)

交换给定值

1) 交换 ab此重载只有在 std::is_move_constructible_v<T> && std::is_move_assignable_v<T>true 时才会参与重载决议。 (C++17 起)
2) 交换 ab 数组。等效于调用 std::swap_ranges(a, a + N, b)此重载只有在 std::is_swappable_v<T2>true 时才会参与重载决议。 (C++17 起)

参数

a, b - 要交换的值
类型要求
-
T 必须符合可复制构造 (CopyConstructible) 可复制赋值 (CopyAssignable) (C++11 前)可移动构造 (MoveConstructible) 可移动赋值 (MoveAssignable) (C++11 起)的要求
-
T2 必须符合可交换 (Swappable) 的要求。

返回值

(无)

异常

1)

(无)

(C++11 前)
noexcept 说明:  
noexcept(

    std::is_nothrow_move_constructible<T>::value &&
    std::is_nothrow_move_assignable<T>::value

)
(C++11 起)
2)
noexcept 说明:  
noexcept(noexcept(swap(*a, *b)))
异常规定中标识符 swap 的查找在通常查找规则的所找到的任何内容外,还会找到此函数模板,这使得异常规定等价于 C++17 std::is_nothrow_swappable
(C++11 起)
(C++17 前)
noexcept 说明:  
(C++17 起)

复杂度

1) 常量
2) 与 N 成线性

特化

std::swap 可以对程序定义类型在命名空间 std 中特化,但 ADL 不会寻找这些特化(命名空间 std 不是与程序定义类型关联的空间)。

(C++20 前)

令程序定义类型可交换的期待方式是在与该类型相同的命名空间中提供非成员函数 swap :细节见可交换 (Swappable)

标准库已提供下列重载:

特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数)
std::swapunique_lock 的特化
(函数模板)
std::swapshared_lock 的特化
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数)
特化 std::swap 算法
(函数模板)
特化 std::swap 算法
(函数模板)
交换二个路径
(函数)
特化 std::swap 算法
(函数)
特化 std::swap 算法
(函数)
重载 std::swap 算法
(函数)
特化 std::swap 算法
(函数)
特化 std::swap 算法
(函数)

示例

#include <algorithm>
#include <iostream>
 
namespace Ns
{
    class A
    {
        int id{};
 
        friend void swap(A& lhs, A& rhs)
        {
            std::cout << "swap(" << lhs << ", " << rhs << ")\n";
            std::swap(lhs.id, rhs.id);
        }
 
        friend std::ostream& operator<< (std::ostream& os, A const& a)
        {
            return os << "A::id=" << a.id;
        }
 
    public:
        A(int i) : id{i} {}
        A(A const&) = delete;
        A& operator = (A const&) = delete;
    };
}
 
int main()
{
    int a = 5, b = 3;
    std::cout << a << ' ' << b << '\n';
    std::swap(a, b);
    std::cout << a << ' ' << b << '\n';
 
    Ns::A p{6}, q{9};
    std::cout << p << ' ' << q << '\n';
//  std::swap(p, q);  // 错误,不满足类型要求
    swap(p, q);       // OK:实参依赖查找找到了合适的友元 swap
    std::cout << p << ' ' << q << '\n';
}

输出:

5 3
3 5
A::id=6 A::id=9
swap(A::id=6, A::id=9)
A::id=9 A::id=6

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 出版时的行为 正确行为
LWG 227 C++98 T 不需要满足可复制构造 (CopyConstructible)
可默认构造 (DefaultConstructible) (因此不保证能构造 T 类型的临时对象)
T 也需要满足
可复制构造 (CopyConstructible)
LWG 809 C++98 数组无法交换 添加重载 (2)
LWG 2554 C++11 因为名称查找问题,交换多维数组无法是 noexcept 使之可能

参阅

交换两个对象的值
(定制点对象)
交换两个迭代器所指向的元素
(函数模板)
交换两个范围的元素
(函数模板)
(C++14)
将实参替换为一个新值,并返回其先前值
(函数模板)