使用void指针生成无重复枚举数组出现重复,代码何处有误?
问题分析与修复方案
嘿,我帮你找出问题所在啦!你遇到的重复元素问题,核心是重复检查逻辑完全失效,还有几处小的逻辑冗余,下面一步步给你拆解说明:
1. 最关键的错误:重复检查比错了对象
你的isDuplicate函数里直接用*q == p做比较——但每个getAFruitVP()都会通过new Fruit创建一个全新的对象,所以每个指针的内存地址都是独一无二的!哪怕两个指针指向的枚举值完全相同,它们的地址也不一样,导致*q == p永远返回false,重复检查根本起不到作用。
修正后的isDuplicate函数
我们需要把VoidPtr强制转换成Fruit*,然后比较指针指向的实际枚举值,而不是指针本身:
bool isDuplicate(VoidPtr *vpArray, int size, VoidPtr p) { Fruit* target = static_cast<Fruit*>(p); VoidPtr *q = &vpArray[0]; for(int j = 0; j < size; j++) { Fruit* current = static_cast<Fruit*>(*q); // 比较枚举值,而非指针地址 if (*current == *target) { return true; } ++q; } return false; }
2. constructVPArray里的冗余赋值
看这段代码:
*p = getAFruitVP (); do { *p = getAFruitVP (); }while (isDuplicate(vpArray, i, *p));
你先给*p赋值了一次,然后立刻在do块里又重新赋值覆盖了它,这完全是多余的。而且当i=0时,isDuplicate的size参数是0,循环不会执行,直接返回false,所以我们只需要保留do-while内部的赋值即可:
修正后的constructVPArray函数
void constructVPArray (VoidPtr *vpArray, int size) { VoidPtr *p = &vpArray[0]; for (int i = 0; i < size; i++) { do { *p = getAFruitVP(); } while (isDuplicate(vpArray, i, *p)); ++p; } }
3. 额外注意:MAXNO的值要匹配枚举数量
你的getAFruitVP里用了rand() % MAXNO,而你的Fruit枚举有7个成员(从Durian到Berry),所以MAXNO必须定义为7,否则会生成超出枚举范围的数值,导致未定义行为:
#define MAXNO 7
完整修正后的代码
我把所有修正点整合,还加上了内存释放的逻辑(避免内存泄漏)和测试输出:
#include <iostream> #include <cstdlib> #include <ctime> using namespace std; enum Fruit {Durian, Papaya, Apple, Orange, Mango, Jackfruit, Berry}; #define MAXNO 7 using VoidPtr = void*; VoidPtr getAFruitVP () { int k = rand() % MAXNO; Fruit f = static_cast<Fruit>(k); Fruit *fruitPtr = new Fruit; *fruitPtr = f; VoidPtr vp = fruitPtr; return vp; } bool isDuplicate(VoidPtr *vpArray, int size, VoidPtr p) { Fruit* target = static_cast<Fruit*>(p); VoidPtr *q = &vpArray[0]; for(int j = 0; j < size; j++) { Fruit* current = static_cast<Fruit*>(*q); if (*current == *target) { return true; } ++q; } return false; } void constructVPArray (VoidPtr *vpArray, int size) { VoidPtr *p = &vpArray[0]; for (int i = 0; i < size; i++) { do { *p = getAFruitVP(); } while (isDuplicate(vpArray, i, *p)); ++p; } } int main () { srand(time(NULL)); VoidPtr* vpArray; int size = rand() % 7; // 生成0-6的数组大小,你也可以改成1+rand()%7来生成1-7的大小 vpArray = new VoidPtr[size]; constructVPArray(vpArray, size); // 测试输出:打印数组中的枚举值 cout << "Generated array (size " << size << "):" << endl; for (int i = 0; i < size; i++) { Fruit* f = static_cast<Fruit*>(vpArray[i]); cout << *f << endl; } // 释放内存,避免泄漏 for (int i = 0; i < size; i++) { delete static_cast<Fruit*>(vpArray[i]); } delete[] vpArray; return 0; }
最后提一句内存泄漏
你的原始代码没有释放new出来的Fruit对象和VoidPtr数组,这会导致内存泄漏,上面的完整代码已经补上了释放逻辑,记得使用动态分配的内存后一定要清理哦!
内容的提问来源于stack exchange,提问作者skyzhuzhu
相关产品推荐
相关产品推荐

