c++ - c template




為什麼std:: swap有這麼多特化? (4)

在查看std::swap的文檔時,我看到了很多專業化。
看起來每個STL容器以及許多其他std工具都有專門的交換。
我想藉助模板,我們不需要所有這些專業化?

例如,
如果我編寫自己的pair它可以與模板化版本一起正常工作:

template<class T1,class T2> 
struct my_pair{
    T1 t1;
    T2 t2;
};

int main() {
    my_pair<int,char> x{1,'a'};
    my_pair<int,char> y{2,'b'};
    std::swap(x,y);
} 

那麼從專業化std::pair獲得了什麼呢?

template< class T1, class T2 >
void swap( pair<T1,T2>& lhs, pair<T1,T2>& rhs );

我也想知道我是否應該為自定義類編寫自己的專業,
或者只是依靠模板版本。


那麼從專業化std :: pair中獲得了什麼呢?

性能。 通用交換通常足夠好(從C ++ 11開始),但很少是最優的(對於std::pair ,對於大多數其他數據結構)。

我也想知道我是否應該為自定義類編寫自己的專業,或者只是依賴於模板版本。

我建議默認依賴模板,但如果分析顯示它是瓶頸,請知道可能存在改進的空間。 過早優化和所有......


std::swap是按照以下代碼行實現的:

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

(有關更多信息,請參閱“標準庫如何實現std :: swap?” 。)

那麼從專業化std::pair獲得了什麼呢?

std::swap可以通過以下方式進行專門化libc++簡化

void swap(pair& p) noexcept(is_nothrow_swappable<first_type>{} &&
                            is_nothrow_swappable<second_type>{})
{
    using std::swap;
    swap(first,  p.first);
    swap(second, p.second);
}

如您所見,使用ADL直接在對的元素上調用swap :這允許在firstsecond上使用定制的和可能更快的swap 實現(這些實現可以利用元素的內部結構的知識以獲得更多表現)

(有關更多信息,請參閱“如何using std::swap啟用ADL?” 。)


原因是性能,特別是pre c ++ 11。

考慮類似“矢量”類型的東西。 Vector有三個字段:大小,容量和指向實際數據的指針。 它的複制構造函數和復制賦值複製實際數據。 C ++ 11版本還有一個移動構造函數和移動賦值,用於竊取指針,將源對像中的指針設置為null。

專用的Vector交換實現可以簡單地交換字段。

基於復制構造函數,複製賦值和析構函數的通用交換實現將導致數據複製和動態內存分配/釋放。

基於移動構造函數,移動賦值和析構函數的通用交換實現將避免任何數據複製或內存分配,但它會留下一些冗餘的歸零和空值檢查,優化器可能會或可能無法優化。

那麼為什麼要對“Pair”進行專門的交換實現呢? 對於一對int和char,沒有必要。 它們是普通的舊數據類型,因此通用交換就可以了。

但是,如果我有一對說Vector和String怎麼辦? 我想對這些類型使用專家交換操作,因此我需要在對類型上進行交換操作,通過交換它的組件元素來處理它。


據推測,這是出於性能原因,因為這pair包含的類型交換成本低,但複製成本很高,如vector 。 由於它可以在firstsecond上調用swap而不是使用臨時對象進行複制,因此它可以顯著提高程序性能。







template-specialization