1. 程式人生 > >針對交換操作——考慮寫一個不拋異常的swap函式。

針對交換操作——考慮寫一個不拋異常的swap函式。

近日在研究share ptr的原始碼,第一遍看的時候對於裡面的swap函式不以為然,反覆再三之後才知到其中奧妙,於是,在這裡,我來談談swap函式的理解,為接下來的share ptr的原始碼分析做鋪墊。

swap是異常安全程式設計的脊柱,以及用來處理自我賦值可能性的一個常用機制。

首先,咱們來看看典型的swap實現:

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

我們想要交換兩個物件,經典實現就是,我再造一個一模一樣的臨時物件,然後你們開始交換,交換完以後,我把臨時物件的記憶體釋放。當然這段程式碼真的是一點亮點都沒有,而且,大部分也都是用這個方法,並且絕對是安全的,但是,我們想想,倘若我們有一種型別, 是用一個指標指向一個物件,內部含有真正的資料。對於這種型別,我們想要交換兩個物件的值,就可以把複雜度降到最低:我們只需要交換兩個指標就可以了,這就是大名鼎鼎的pimpl手法,也是橋接模式的一個變種,對於這種手法,我就舉一個最簡單的例子:

class myimpl{
public:
...
private:
  int x,y,z;
  std::queue<int> que;
  sta::stack<int> sta;
};
class my{
public:
  ...
private:
  myimpl *impl;
};

看第二個類,第二個類的private裡面就只有一個指向第一個類的指標。我們想要交換,就只需要交換指標就可以了。

再回顧一下我之前實現的smartptr類,裡面也是有指標,然而怎麼才能告訴編譯器我要交換指標。

這裡要引入一個偏特化的概念,我們把swap偏特化,寫一個特定的swap就可以了:

void swap(myimpl &p1)
{
  using std::swap;
  swap(impl,p1.impl);
}

我們在swap裡面using宣告swap,這樣就可以由編譯器選擇最合適的版本,交換指標,當然這是異常安全的版本。