void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
这个算法有如下几个问题:
1.
类型安全性:使用者必须自行保证
base
指向的数组的元素类型和
compar
的两个参数的类型是一致的;使用者必须自行保证
size
必须是数组元素类型的大小。
2.
通用性:
qsort
对参数数组的二进制接口有严格要求——它必须是一个内存连续的数组。如果你实现了一个巧妙的、分段连续的自定义数组,就没法使用
qsort
了。
3.
接口直观性:如果你有一个数组
char* arr = new arr[10];
那么该数组的元素类型其实就已经“透露”了它自己的大小。然而
qsort
把数组的元素类型给“
void
”掉了(
void *base
),于是丢失掉了这一信息,而只能让调用方手动提供一个
size
。为什么要把数组类型声明为
void*
?因为除此之外别无它法,声明为任意一个类型的指针都不妥(
compar
的参数类型也是如此)。
qsort
为了通用性,把类型信息丢掉了,进而导致了必须用额外的参数来提供类型大小信息。在这个特定的算法里问题还不明显,毕竟只多一个
size
参数而已,但一旦涉及的类型信息多了起来,其接口的可伸缩性(
scalability
)问题和直观性问题就会逐渐显现。
4.
效率:
compar
是通过函数指针调用的,这带来了一定的开销。但跟上面的其它问题比起来这个问题还不是最严重的。