C++ utility swap 函数

  • 定义和用法

    C++ 98 C++ 11
    // defined in <algorithm> before C++11
    template <class T> void swap (T& a, T& b);
    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)));
    std::swap 交换两个对象的值,交换a和b的值。
  • 声明

    C++ 98 C++ 11
    在C++ 11之前,此函数在<algorithm>中定义。

    template <class T> void swap ( T& a, T& b )
    {
      T c(a); a=b; b=c;
    }
    请注意,这个函数涉及到一个复制构造和两个赋值操作,这可能不是交换存储大量数据的类内容的最有效方式,因为这些操作中的每一个操作通常在与其大小相关的线性时间内进行。
    大型数据类型可以提供此函数的重载版本,从而优化其性能。值得注意的是,所有标准容器专门化它的方式是,只有少数内部指针被交换,而不是它们的全部内容,使它们在常量时间内操作。
    这些函数模板的行为相当于:

    
    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)调用交换无条件地允许定制过载对非基本面的类型被称为代替这个泛型版本:定制过载的交换相同的名称空间中声明的类型提供了通过选择名字查找在这个通用版本。
  • 参数

    a,b两个对象,其内容交换。
    C++ 98 C++ 11
    类型T应该是可复制构造和可分配的。 类型T应该是可构造移动和可分配移动的(或者为它定义了交换,对于版本(2))。
  • 返回值

    没有返回值。
  • 示例

    
    // 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
    
  • 复杂性

    非数组:Constant:只执行一次构造和两次赋值(但请注意,每个操作都有其自身的复杂性)。
    数组:N中的线性:对每个元素执行交换操作。
  • 数据竞争

    a和b都做了修改
  • 异常

    如果类型T的构造或赋值发生抛出。如果T是nothrow-move-constructible和nothrow-move-assignable,不要抛出。注意,如果T不满足上面(在参数中)指定的需求,它将导致未定义的行为。
  • 相关页面

    copy 复制元素的范围(函数模板)
    fill 用值填充范围(函数模板)
    replace 替换范围内的值(函数模板)