来自 C++ 编程语言的排序示例

Sort example from C++ Programming Language

我将在 "C++ Programming Language" 中查看以下示例代码:

typedef int (*CFT) (const void*, const void*);

void ssort(void* base, size_t n, size_t sz, CFT cmp) {
    for (int gap = n / 2; 0 < gap; gap /= 2) {
        for (int i = gap; i < n; i++) {
            for (int j = i - gap; 0 <= j; j -= gap) {
                char* b = static_cast<char*>(base);
                char* pj = b + j * sz;
                char* pig = b + (j + gap) * sz;

                if (cmp(pig, pj) < 0) {
                    for (int k = 0; k < sz; k++) {
                        std::swap(pj[k], pig[k]);
                    }
                } else {
                    break;
                }
            }
        }
    }
}

int cmp(const void* a, const void* b) {
    return *(static_cast<const int*>(a)) - *(static_cast<const int*>(b));

}

谁能解释一下这些转换为 char* 的内容是什么?我们如何使用 char* 指向任何类型的值?

static_cast<T> 只是尝试将类型转换为类型 T。看这里的例子 -

float f = 12.3;
float* pf = &f;

// static cast<>
// OK, n = 12
int n = static_cast<int>(f);
// Error, types pointed to are unrelated
//int* pn = static_cast<int*>(pf);
// OK
void* pv = static_cast<void*>(pf);
// OK, but *pn2 is rubbish
int* pn2 = static_cast<int*>(pv);

// reinterpret_cast<>
// Error, the compiler know you should
// call static_cast<>
//int i = reinterpret_cast<int>(f);
// OK, but *pn is actually rubbish, same as *pn2
int* pi = reinterpret_cast<int*>(pf);

礼貌:what static cast actually doing
并且您不能 user char* 指向任何类型的值。

记住这是一个示例,通过说明 C 编程中的弱点来演示 不是 如何在 C++ 中做事在处理 generics.

引用: C++ 编程语言(第 4 版第 334 页)

This style of code is common in C, but it is not the most elegant way of expressing this algorithm in C++

然而:

char* b = static_cast<char*>(base);
char* pj = b + j * sz;
char* pig = b + (j + gap) * sz;

原因 void 指针被转换为 char 指针是因为你不能在 void* 上进行指针运算。

指针算法以指针指向的对象的大小单位工作。所以要进行指针运算,编译器需要知道指针的类型,这样它才能知道如何对其值进行加减。

这对于 void* 是不可能的,因为 void 没有大小。通过接受 void* 参数,原来的 type 已经丢失。

为了解决这个问题,算法将 void* 转换为 char*char*one 的大小单位工作。该函数然后期望用户将每个元素的实际大小作为另一个参数传递。

编译器对结果 char*.

进行算术运算没有问题

因为 ssort() 函数不知道它正在排序的元素的 类型 调用者还需要 传入 自己的函数来做元素之间的比较。请注意 传入的 函数会将 void* 参数转换为正确的类型。

这是有效的,因为调用 ssort() 函数的人知道要排序的 typessort() 函数不需要。

这给函数调用者带来了很大的负担,并且有 很多 的错误余地,导致细微或不那么细微的错误。

C++.

中,应像避免瘟疫 一样避免此类编程

总结一下:

ssort() 函数将 void* 转换为 char* 以便它可以进行指针运算来定位需要比较的元素。

调用者 传入他们自己的函数 (cmp),该函数将 void* 转换为 正确的类型 ,以便进行比较