​C++ Swap函數有幾種寫法?

  • 2019 年 11 月 6 日
  • 筆記

在說C++模板的方法前,我們先想想C語言裡面是怎麼做交換的。

舉個例子,要將兩個int數值交換,是不是想到下面的程式碼:

void swap(int&a , int &b)  {      int t = a;      a=b;      b=t;  }

如果要求不用臨時變數,可考慮異或的方式。

void swap(int&a,int&b)  {      if (&a != &b)      {          a ^= b;          b ^= a;          a ^= b;      }  }

整型數比較容易理解,如果是字元串呢?字元串交換不能直接使用上面類似的方法賦值,想想原因是啥?:)

//偽程式碼  void swap(char* a,int sizeofa,char*b,int sizeofb)  {      char temp[MAX] ={0};      strncpy(temp,sizeof(temp)-1,a) ;      strncpy(a,sizeofa-1,b);      strncpy(b,sizeofb-1,temp) ;  }

當然如果還可以用指針的指針。

void swap(char** a , char** b)  {      char* tmp = *a ;      *a= *b;      *b= tmp ;  }

上面的方法都是按特定的類型做的處理,有沒更通用的寫法?

我們來看看C++ 怎麼處理交換:

void swap(string& a , string&b)  {      string c(a) ;      a=b;      b=c;  }

是不是和int的很像?

我們再來看看標準庫裡面swap的演算法是怎麼實現的:

namespace std {      template<typename T>      void swap(T &a,T &b) {          T temp(a);          a = b;          b = temp;      }  }

template 是c++裡面很重要的概念,利用模板可以實現很多通用的演算法。上面的std::swap要求T類實現拷貝構造函數,並且和上面幾個實現一樣都需要做賦值運算,在海量的交易請求裡面會損耗性能。

因此在C++11的標準裡面對實現做了優化。看看上面字元串類的交換隻需要交換地址即可,根據這種思路在通用的swap只交換指針,而不是賦值。這樣的實現能將性能提高不少,對大型對象效率明顯提現。

template<typename T>  void swap(T& a,T&b) {      T temp(std::move(a));      a = std::move(b);      b = std::move(temp);  }

std::move 是不是很陌生:)它是C++11的新概念,在內部實現只是做了cast。

template<typename T>  decltype(auto) move(T&& param)  {      using ReturnType = remove_reference_t<T>&&;      return static_cast<ReturnType>(param);  }