【发布时间】:2019-12-24 20:33:45
【问题描述】:
您好,我有一个简单的问题:
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,只是为了区分来自复制分配运算符的排序调用。
【问题讨论】:
-
std::sort如果元素个数为 32 或更少,则使用插入排序,否则使用快速排序。 -
@Evg 这是一个要求还是对这个特定上下文的解释?
-
@FrançoisAndrieux,这是微软标准库的实现细节。我的猜测是,这是 OP 观察到的行为的原因。我目前正在研究源代码以获取更多详细信息。
-
来源的相关部分是:
while (_ISORT_MAX < (_Count = _Last - _First) && 0 < _Ideal)其中_ISORT_MAX的值是 32。<algorithm>的第 3447 行使用 VS 16.5.0 -
在任何语言的任何现代标准库中都没有使用真正的快速排序。全部使用修改后的混合版本,仅当元素数量足够大时才进行快速排序。例如,Java 和 Python 使用 Timsort,而 .NET 框架和 GCC 的 C++ 库使用 Introsort。 libstdc++ 和 libc++ 也对短序列使用插入排序。见What algorithms are used in C++11 std::sort in different STL implementations?