为什么仅当我的容器包含超过 32 个元素时才由 std::sort 调用交换?
Why is swap called by std::sort only if my container has more than 32 elements?
你好我有一个简单的问题:
class A
{
public:
A(int);
A(const A&);
A& operator=(const A&);
~A();
private:
int* ptr_;
friend bool operator<(const A&, const A&);
friend void swap(A&, A&);
};
A::A(int x) :
ptr_(new int(x))
{}
A::A(const A& rhs) :
ptr_(rhs.ptr_ ? new int(*rhs.ptr_) : nullptr)
{}
A& A::operator = (const A & rhs)
{
int* tmp = rhs.ptr_ ? new int(*rhs.ptr_) : nullptr;
delete ptr_;
ptr_ = tmp;
return *this;
}
A::~A()
{
delete ptr_;
}
bool operator<(const A& lhs, const A& rhs)
{
cout << "operator<(const A&, const A&)" << endl;
return *lhs.ptr_ < *rhs.ptr_;
}
void swap(A& lhs, A& rhs)
{
cout << "swap(A&, A&)" << endl;
using std::swap;
swap(lhs.ptr_, rhs.ptr_);
}
int main()
{
std::vector<A> v{ 33,32,31,30,29,28,27,26,25,24,23,22, 21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5, 4,3,2,1 };
std::sort(v.begin(), v.end());
}
如果元素超过 32 个,排序调用 swap
。对于 32 个或更少的元素,元素仍会排序,但不会调用 swap
。
- 我在 x64 上使用 MSVC++ 2019。
- 什么时候调用
swap
什么时候不调用,为什么?谢谢!
- 我没有在复制赋值中使用
swap
只是为了区分复制赋值运算符对它的调用。
Microsoft std::sort
实现 looks 像这样:
const int ISORT_MAX = 32; // maximum size for insertion sort
template<class RanIt, class Diff, class Pr>
void Sort(RanIt First, RanIt Last, Diff Ideal, Pr Pred)
{
Diff Count;
for (; ISORT_MAX < (Count = Last - First) && 0 < Ideal; )
{ // divide and conquer by quicksort
pair<RanIt, RanIt> Mid = Unguarded_partition(First, Last, Pred);
// ...
}
if (ISORT_MAX < Count)
{ // heap sort if too many divisions
Make_heap(First, Last, Pred);
Sort_heap(First, Last, Pred);
}
else if (1 < Count)
Insertion_sort(First, Last, Pred); // small
}
当要排序的范围有32个元素或更少时,Sort
使用插入排序。插入排序在其 implementation. Otherwise, divide-and-conquer quick sort is used. In the implementation it calls iter_swap
(inside Unguarded_partition
), which 中不使用 swap
依次调用 swap
:
template<class FwdIt1, class FwdIt2>
void iter_swap(FwdIt1 Left, FwdIt2 Right)
{ // swap *Left and *Right
swap(*Left, *Right);
}
所有这些都是实施细节。它们因一个标准库实现而异。
你好我有一个简单的问题:
class A
{
public:
A(int);
A(const A&);
A& operator=(const A&);
~A();
private:
int* ptr_;
friend bool operator<(const A&, const A&);
friend void swap(A&, A&);
};
A::A(int x) :
ptr_(new int(x))
{}
A::A(const A& rhs) :
ptr_(rhs.ptr_ ? new int(*rhs.ptr_) : nullptr)
{}
A& A::operator = (const A & rhs)
{
int* tmp = rhs.ptr_ ? new int(*rhs.ptr_) : nullptr;
delete ptr_;
ptr_ = tmp;
return *this;
}
A::~A()
{
delete ptr_;
}
bool operator<(const A& lhs, const A& rhs)
{
cout << "operator<(const A&, const A&)" << endl;
return *lhs.ptr_ < *rhs.ptr_;
}
void swap(A& lhs, A& rhs)
{
cout << "swap(A&, A&)" << endl;
using std::swap;
swap(lhs.ptr_, rhs.ptr_);
}
int main()
{
std::vector<A> v{ 33,32,31,30,29,28,27,26,25,24,23,22, 21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5, 4,3,2,1 };
std::sort(v.begin(), v.end());
}
如果元素超过 32 个,排序调用 swap
。对于 32 个或更少的元素,元素仍会排序,但不会调用 swap
。
- 我在 x64 上使用 MSVC++ 2019。
- 什么时候调用
swap
什么时候不调用,为什么?谢谢! - 我没有在复制赋值中使用
swap
只是为了区分复制赋值运算符对它的调用。
Microsoft std::sort
实现 looks 像这样:
const int ISORT_MAX = 32; // maximum size for insertion sort
template<class RanIt, class Diff, class Pr>
void Sort(RanIt First, RanIt Last, Diff Ideal, Pr Pred)
{
Diff Count;
for (; ISORT_MAX < (Count = Last - First) && 0 < Ideal; )
{ // divide and conquer by quicksort
pair<RanIt, RanIt> Mid = Unguarded_partition(First, Last, Pred);
// ...
}
if (ISORT_MAX < Count)
{ // heap sort if too many divisions
Make_heap(First, Last, Pred);
Sort_heap(First, Last, Pred);
}
else if (1 < Count)
Insertion_sort(First, Last, Pred); // small
}
当要排序的范围有32个元素或更少时,Sort
使用插入排序。插入排序在其 implementation. Otherwise, divide-and-conquer quick sort is used. In the implementation it calls iter_swap
(inside Unguarded_partition
), which 中不使用 swap
依次调用 swap
:
template<class FwdIt1, class FwdIt2>
void iter_swap(FwdIt1 Left, FwdIt2 Right)
{ // swap *Left and *Right
swap(*Left, *Right);
}
所有这些都是实施细节。它们因一个标准库实现而异。