簡體   English   中英

標准庫是如何實現 std::swap 的?

[英]How does the standard library implement std::swap?

STL中swap函數是如何實現的? 是不是就這么簡單:

template<typename T> void swap(T& t1, T& t2) {
    T tmp(t1);
    t1=t2;
    t2=tmp;
}

在其他帖子中,他們討論了為您自己的班級專門化此功能。 為什么我需要這樣做? 為什么我不能使用std::swap函數?

std::swap是如何實現的?

是的,問題中提出的實現是經典的 C++03 實現。

std::swap的更現代 (C++11) 實現如下所示:

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

這是在資源管理方面對經典 C++03 實現的改進,因為它可以防止不需要的副本等。它,C++11 std::swap ,要求類型TMoveConstructibleMoveAssignable ,從而允許實施和改進。

為什么我需要提供自定義實現?

當您的實現比標准版本更高效或更具體時,通常會建議對特定類型的swap自定義實現。

一個經典的(C++11 之前的)示例是當您的類管理大量資源時,復制和刪除這些資源的成本很高。 相反,您的自定義實現可以簡單地交換實現交換所需的句柄或指針。

隨着std::move和可移動類型(並以此實現您的類型)的出現,大約在 C++11 及以后,這里的許多原始基本原理開始消失; 但是,如果自定義交換比標准交換更好,請實施它。

如果通用代碼適當地使用ADL機制,它通常能夠使用您的自定義swap

STL中swap函數是如何實現的?

哪個實現? 這是一個規范,而不是一個具體的庫。 如果你的意思是我的編譯器的標准庫如何做到的,要么告訴我們是哪個編譯器,要么自己閱讀代碼。

是不是就這么簡單:

這本質上是 C++11 之前的原始版本。

這種非專業化的實現強制復制:對於您的示例中的T = std::vector<SomethingExpensive> ,代碼轉換為:

template<typename T> void swap(T& t1, T& t2) {
  T tmp(t1); // duplicate t1, making an expensive copy of each element
  t1=t2;     // discard the original contents of t1,
             // and replace them with an expensive duplicate of t2
  t2=tmp;    // discard the original contents of t2,
             // and replace them with an expensive duplicate of tmp
}            // implicitly destroy the expensive temporary copy of t1

所以為了交換兩個向量,我們基本上創建了三個 有三個動態分配和許多昂貴的對象復制,並且這些操作中的任何一個都可能拋出,可能使參數處於不確定狀態。

由於這顯然很糟糕,因此為昂貴的容器提供了重載,並且鼓勵您為自己的昂貴類型編寫重載:例如。 std::vector可以訪問向量的內部結構,並且可以交換兩個向量而無需進行所有復制:

template <typename T> void swap(vector<T> &v1, vector<T> &v2) { v1.swap(v2); }
template <typename T> void vector<T>::swap(vector<T>& other) {
  swap(this->size_, other.size_); // cheap integer swap of allocated count
  swap(this->used_, other.used_); // cheap integer swap of used count
  swap(this->data__, other.data_); // cheap pointer swap of data ptr
}

請注意,這根本不涉及任何昂貴的副本,沒有動態(取消)分配,並且保證不會拋出。

現在,這種特殊化的原因是 vector::swap 可以訪問 vector 的內部結構,並且可以安全有效地移動它們而無需復制。

為什么我需要做這件事[專門...為你自己的班級]?

Pre-C++11,出於與std::vector相同的原因 - 使交換高效且異常安全。

從 C++11 開始,你真的不需要——如果你提供移動構造和賦值,或者編譯器可以為你生成合理的默認值。

新的通用交換:

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

可以使用移動構造/分配來獲得與上面的自定義向量實現基本相同的行為,而根本不需要編寫自定義實現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM