簡體   English   中英

STL排序是使用交換還是二進制復制?

[英]Does STL sort use swap or binary copy?

我很難找到一個好的答案。 出於某種原因,我認為STL排序將使用swap實現以更好地支持復雜類型,但是當我最終挖掘代碼時,它似乎實際上正在進行二進制復制。 有人能證實嗎? 我猜二進制副本實際上更適合交換。

問題 :是否使用交換實現了任何STL算法或容器操作? (顯然在std::swap之外。)我想知道何時為復雜類型實現我自己的交換是謹慎的。

編輯:我問的原因是你是否有類似的東西:

class MyClass {
  vector<int> vec_data;
  int a;
  int b;
}
vector<MyClass> my_vec;
sort(my_vec.begin(), my_vec.end(), MyCustomCompare);

我想確保排序不是調用向量的復制構造函數,如果調用MyData的默認復制構造函數,就會發生這種情況。 因此我的問題是排序調用交換,復制分配等?

不,來自C ++標准庫的std::sort不允許對具有非平凡復制/賦值運算符的對象執行二進制復制。 我不明白為什么它不能在具有普通復制/賦值運算符的對象上進行二進制復制。 考慮這個對象:

class Explosive {
    Explosive* const self;
public:
    Explosive() :self(this) {}
    Explosive(const Explosive&) :self(this) {}
    ~Explosive() {assert(this==self);}
    Explosive& operator=(const Explosive& rhs) {
        assert(this==self && rhs.self==&rhs); 
        return *this;
    }
    bool operator<(const Explosive& rhs) const 
    {return std::less<Explosive*>(self,rhs.self);}
};

保證C ++算法不會引發斷言,這意味着二進制副本無效。

我之前見過std::copy在GNU libstdc ++中使用memmove ,具體取決於元素類型是否 為POD has_trivial_assignment_operator 這里查看來源

template<typename _Tp>
   inline _Tp*
   __copy_trivial(const _Tp* __first, const _Tp* __last, _Tp* __result)
   {
      std::memmove(__result, __first, sizeof(_Tp) * (__last - __first));
      return __result + (__last - __first);
   }

至少在SGI中, rotatereverseswap_rangesrandom_shufflepartitionnext_permutation都使用swap

http://www.sgi.com/tech/stl/stl_algo.h

此外,第25.4.1.1節中特別提到了std::sort的c ++ 11標准文檔:

要求RandomAccessIterator應滿足ValueSwappable (17.6.3.2)的要求。 *first的類型應滿足MoveConstructible (表20)和MoveAssignable (表22)的要求。

現在§17.6.3.2包含:

當且僅當以下情況時,對象t可與對象u交換:

  • 當在下面描述的上下文中計算時swap(t, u)表達式swap(t, u)swap(u, t)是有效的
  • 這些表達式具有以下效果:
    • 由t引用的對象具有由u和最初持有的值
    • u引用的對象具有最初由t保持的值。

評估swap(t, u)swap(u, t)的上下文應確保在候選集上通過重載解析(13.3)選擇名為“swap”的二進制非成員函數,該候選集包括:

  • (20.2)和中定義的兩個交換函數模板
  • 由參數依賴查找(3.4.2)生成的查找集。

這取決於您的STL實現。 GCC STL實現使用introsort和插入排序的組合。 似乎將在introsort循環中調用std::swap (或您的特化),但插入排序不會調用它。

如果你沒有std::swap ,那么默認的std::swap實現將使用臨時副本來實現swap。

它不使用二進制副本(某些POD類型除外,它們可能具有隱藏在STL庫深處的特化)。

此外,在C ++ 0x中,插入排序似乎可能會使用移動語義(rvalue references)。

它交換,但由於它是一個模板函數,它可能會內聯交換代碼。 如果它是一個簡單類型,編譯器可以選擇將二進制交換作為優化。

暫無
暫無

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

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