八叉树查找RGB点时如何返回目标父节点/兄弟列表及修复vector编译错误
八叉树find函数编译错误修复与需求实现
编译报错原因
触发no viable conversion from returned value of type 'nullptr_t' to function return type 'vector<Octree *>'的直接原因:函数声明的返回类型是vector<Octree*>,但空节点分支直接返回了nullptr,二者不存在C隐式转换规则,编译器无法完成类型匹配。
*修复方式:所有代表查找失败、空节点的返回分支,不要返回nullptr,改为返回空的vector实例,即写return {};即可,这是C11后支持的类构造简化写法,会直接生成一个无元素的同类型vector。*
原代码的隐藏问题
除了编译错误,原代码还有两处会引发运行异常的逻辑漏洞:
- 当子节点是带RGB值的有效节点、但RGB和目标不匹配时,函数没有设置返回值,会触发未定义行为
- 递归调用时直接透传下层find的返回值,无法保证最终返回的列表是目标节点同层级的兄弟节点集合,也无法关联到对应父节点
需求适配的修改逻辑
结合“返回目标节点的父节点指针、或返回包含目标节点+所有兄弟节点的列表”的需求,可按如下规则调整:
- 当遍历到目标RGB点所在的子节点时,当前正在遍历的
this节点就是目标的直接父节点 - 父节点持有的
children数组本身就是包含目标节点、以及其余7个兄弟节点的指针集合,可直接作为返回值 - 所有查找失败的分支(空占位节点、非匹配的有效节点)统一返回空vector
修复后的参考代码
vector<Octree*> Octree::find(int R, int G, int B) { int midR = (topLeftFront->R + bottomRightBack->R) / 2; int midG = (topLeftFront->G + bottomRightBack->G) / 2; int midB = (topLeftFront->B + bottomRightBack->B) / 2; int pos = -1; // 计算目标点所属的八分区位置 if (R <= midR) { if (G <= midG) { if (B <= midB) pos = TopLeftFront; else pos = TopLeftBottom; } else { if (B <= midB) pos = BottomLeftFront; else pos = BottomLeftBack; } } else { if (G <= midG) { if (B <= midB) pos = TopRightFront; else pos = TopRightBottom; } else { if (B <= midB) pos = BottomRightFront; else pos = BottomRightBack; } } // 边界保护:防止pos越界访问children数组 if (pos < 0 || pos >= 8) { return {}; } // 遇到内部节点,递归向下查找 if (children[pos]->point == nullptr) { return children[pos]->find(R, G, B); } // 遇到空占位节点,返回空vector else if (children[pos]->point->R == -1) { return {}; } else { // 命中目标RGB点:返回当前父节点的全部子节点(即目标+所有兄弟) if (R == children[pos]->point->R && G == children[pos]->point->G && B == children[pos]->point->B) { return children; } // 非目标的有效节点,返回空vector return {}; } }
补充实现提示
如果需要同时拿到父节点指针,有两种常用实现方案:
- 调整函数返回结构,把当前
this指针作为父节点引用,和兄弟节点列表封装在一起返回 - 由于返回的
children数组是父节点的成员属性,可通过内存偏移反向推导所属的父节点实例
内容的提问来源于stack exchange,提问作者gverenti
相关产品推荐
相关产品推荐

