std::swap() 算法
- 自 C++20 起
- 自 C++11 起
- 直到 C++11
// (1)
template< class T >
constexpr void swap( T& a, T& b ) noexcept(/* see below */);
// (2)
template< class T2, std::size_t N >
constexpr void swap( T2 (&a)[N], T2 (&b)[N] ) noexcept(/* see below */);
// (1)
template< class T >
void swap( T& a, T& b ) noexcept(/* see below */);
// (2)
template< class T2, std::size_t N >
void swap( T2 (&a)[N], T2 (&b)[N] ) noexcept(/* see below */);
// (1)
template< class T >
void swap( T& a, T& b );
// (2)
template< class T2, std::size_t N >
void swap( T2 (&a)[N], T2 (&b)[N] );
交换给定值。
-
(1) 交换值
a
和b
。重载决议此重载不参与重载决议,除非std::is_move_constructible_v<T> && std::is_move_assignable_v<T>
为true
。 (自 C++17 起) -
(2) 交换数组
a
和b
。实际上调用std::swap_ranges(a, a + N, b)
。重载决议此重载不参与重载决议,除非std::is_swappable_v<T2>
为true
。 (自 C++17 起)
参数
a b | 要交换的值。 |
类型要求
T | 可移动构造, 可移动赋值 (自 C++11 起) 可复制构造, 可复制赋值 (直到 C++11) |
T2 | 可交换 |
返回值
(无)
复杂度
- (1) - 常量。
- (1) -
N
的线性。
异常
C++11 之前不抛出异常。
-
(1)
- 自 C++11 起
noexcept 规范
noexcept(
std::is_nothrow_move_constructible<T>::value &&
std::is_nothrow_move_assignable<T>::value
) -
(2)
- 自 C++17 起
- C++17 之前
noexcept 规范
noexcept(std::is_nothrow_swappable_v<T2>)
noexcept 规范
noexcept(
noexcept(swap(*a, *b))
)异常规范中标识符 swap 的查找除了通过常规查找规则找到的内容外,还会找到此函数模板,使得异常规范等同于 C++17 的
std::is_nothrow_swappable
。
带有模板参数 ExecutionPolicy
的重载报告错误如下
- 如果作为算法一部分调用的函数抛出异常,并且
ExecutionPolicy
是标准策略之一,则调用std::terminate
。对于其他ExecutionPolicy
,行为是实现定义的. - 如果算法未能分配内存,则抛出
std::bad_alloc
。
特化
- 直到 C++20
使程序定义类型可交换的预期方法是在与类型相同的命名空间中提供非成员函数 swap:有关详细信息,请参见可交换。
标准库已提供以下重载
std::swap(std::pair) | 特化 |
std::swap(std::tuple) (自 C++11 起) | 特化 |
std::swap(std::shader_ptr) (自 C++11 起) | 特化 |
std::swap(std::weak_ptr) (自 C++11 起) | 特化 |
std::swap(std::unique_ptr) (自 C++11 起) | 特化 |
std::swap(std::function) (自 C++11 起) | 特化 |
std::swap(std::basic_string) | 特化 |
std::swap(std::array) (自 C++11 起) | 特化 |
std::swap(std::deque) (自 C++11 起) | 特化 |
std::swap(std::forward_list) (自 C++11 起) | 特化 |
std::swap(std::list) | 特化 |
std::swap(std::vector) | 特化 |
std::swap(std::map) | 特化 |
std::swap(std::multimap) | 特化 |
std::swap(std::set) | 特化 |
std::swap(std::multiset) | 特化 |
std::swap(std::unordered_map) (自 C++11 起) | 特化 |
std::swap(std::unordered_multimap) (自 C++11 起) | 特化 |
std::swap(std::unordered_set) (自 C++11 起) | 特化 |
std::swap(std::unordered_multiset) (自 C++11 起) | 特化 |
std::swap(std::queue) (自 C++11 起) | 特化 |
std::swap(std::priority_queue) (自 C++11 起) | 特化 |
std::swap(std::stack) (自 C++11 起) | 特化 |
std::swap(std::valarray) (自 C++11 起) | 特化 |
std::swap(std::basic_stringbuf) (自 C++11 起) | 特化 |
std::swap(std::basic_istringstream) (自 C++11 起) | 特化 |
std::swap(std::basic_ostringstream) (自 C++11 起) | 特化 |
std::swap(std::basic_stringstream) (自 C++11 起) | 特化 |
std::swap(std::basic_filebuf) (自 C++11 起) | 特化 |
std::swap(std::basic_ifstream) (自 C++11 起) | 特化 |
std::swap(std::basic_ofstream) (自 C++11 起) | 特化 |
std::swap(std::basic_fstream) (自 C++11 起) | 特化 |
std::swap(std::basic_syncbuf) (自 C++20 起) | 特化 |
std::swap(std::basic_spanbuf) (自 C++23 起) | 特化 |
std::swap(std::basic_ispanstream) (自 C++23 起) | 特化 |
std::swap(std::basic_ospanstream) (自 C++23 起) | 特化 |
std::swap(std::basic_spanstream) (自 C++23 起) | 特化 |
std::swap(std::basic_regex) (自 C++11 起) | 特化 |
std::swap(std::match_results) (自 C++11 起) | 特化 |
std::swap(std::thread) (自 C++11 起) | 特化 |
std::swap(std::unique_lock) (自 C++11 起) | 特化 |
std::swap(std::shared_lock) (自 C++14 起) | 特化 |
std::swap(std::promise) (自 C++11 起) | 特化 |
std::swap(std::packaged_task) (自 C++11 起) | 特化 |
std::swap(std::optional) (自 C++17 起) | 特化 |
std::swap(std::any) (自 C++17 起) | 特化 |
std::swap(std::variant) (自 C++17 起) | 特化 |
std::swap(std::basic_stacktrace) (自 C++17 起) | 特化 |
swap(std::filesystem::path) (自 C++17 起) | 特化(隐藏朋友) |
swap(std::expected) (自 C++23 起) | 特化(隐藏朋友) |
swap(std::jthread) (自 C++20 起) | 特化(隐藏朋友) |
swap(std::move_only_function) (自 C++23 起) | 特化(隐藏朋友) |
swap(std::stop_source) (自 C++20 起) | 特化(隐藏朋友) |
swap(std::stop_token) (自 C++20 起) | 特化(隐藏朋友) |
示例
#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); // error, type requirements are not satisfied
swap(p, q); // OK, ADL finds the appropriate friend `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