[英]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中, rotate
, reverse
, swap_ranges
, random_shuffle
, partition
, next_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.