Olá, tenho uma pergunta simples:
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());
}
Com mais de 32 elementos, a classificação é chamada swap
. Com 32 elementos ou menos, os elementos ainda são classificados, mas swap
não são chamados.
- Estou usando o MSVC ++ 2019 em x64.
- Quando é
swap
chamado e quando não é e por quê? Obrigado! - Não usei
swap
na atribuição de cópias apenas para distinguir entre a chamada e a classificação do operador de atribuição de cópia.
@ Evg Isso é um requisito ou uma explicação para esse contexto específico?
—
François Andrieux
@ FrançoisAndrieux, este é um detalhe de implementação da biblioteca padrão da Microsoft. Meu palpite é que esse é o motivo do comportamento observado pelo OP. Atualmente, estou pesquisando o código-fonte para obter mais detalhes.
—
Evg
Parte relevante da fonte é:
—
ChrisMM
while (_ISORT_MAX < (_Count = _Last - _First) && 0 < _Ideal)
where _ISORT_MAX
é dado o valor de 32. Linha 3447 do <algorithm>
uso do VS 16.5.0
Nenhum quicksort real é usado em qualquer biblioteca padrão moderna em qualquer idioma. Todos usam versões mistas modificadas, que são apenas uma classificação rápida quando o número de elementos é grande o suficiente. Por exemplo, Java e Python usam o Timsort, enquanto o .NET framework e a biblioteca C ++ do GCC usam o Introsort . libstdc ++ e libc ++ também usam classificação de inserção para sequências curtas. Consulte Quais algoritmos são usados no C ++ 11 std :: sort em diferentes implementações STL?
—
phuclv
std::sort
recorre à classificação por inserção se o número de elementos for 32 ou menos e usa a classificação rápida caso contrário.