【发布时间】:2011-09-04 17:17:58
【问题描述】:
std::sort 使用 std::swap 交换元素,而 std::swap 又使用复制构造函数和赋值运算符,保证在交换值时获得正确的语义。
qsort 通过简单地交换元素的底层位来交换元素,忽略与您正在交换的类型相关的任何语义。
即使qsort 不知道您要排序的类型的语义,它仍然非常适用于非平凡类型。如果我没记错的话,它适用于所有标准容器,尽管它们不是 POD 类型。
我认为qsort 在类型T 上正常工作的先决条件是T 是/普通可移动/。在我的脑海中,唯一不能轻易移动的类型是那些具有内部指针的类型。例如:
struct NotTriviallyMovable
{
NotTriviallyMovable() : m_someElement(&m_array[5]) {}
int m_array[10];
int* m_someElement;
};
如果您对NotTriviallyMovable 的数组进行排序,那么m_someElements 最终会指向错误的元素。
我的问题是:还有哪些类型不适用于qsort?
【问题讨论】:
-
我发现这里使用标签
move-semantics有点混乱,因为它通常与C++0x 的移动语义相关。 -
基本上,在 C++ 中对任何非 POD 类型使用
qsort是未定义的行为。从那时起,它会破坏的具体情况以及如何破坏并不那么重要:无论如何你都不应该使用它。 -
你为什么要首先使用
qsort?在我检查过的所有平台上,std::sort都更快(对于可轻松交换的对象类型),而且考虑到内联比较运算符的选项,这是完全合理的。 -
我最后一次测量
std::sort的速度大约是原来的两倍,因为它就地排序(没有内存分配)。使用 C++0x,我们甚至可以免费获得大多数类型的移动构造函数,因此交换变得与位复制一样好……在安全的情况下。那么,您为什么还要打扰qsort呢? -
@Christopher @Matthieu:一个很好的原因是代码膨胀。上次我检查时,每个独特的用法会增加大约 5KB 的代码。在不在热路径上的代码中,最好使用更小的代码而不是更快的代码。此外,即使在热路径中,最好使用 qsort 以便更好地使用 I-cache。
标签: c++ sorting generic-programming qsort move-semantics