set::find() 找不到

set::find() doesn't find

提问人:Josu Goñi 提问时间:1/12/2013 更新时间:1/12/2013 访问量:630

问:

我对这段代码有问题(cubeBoxData是一组cubeBox):

cubeBox temp(bx,by,bz);
cubeBoxData.insert(temp);
set<cubeBox>::iterator i = cubeBoxData.find(temp);
const_cast<cubeBox&>(*i).addCube(x,y,z);

问题是 cubeBoxData.find(temp);找不到 temp,然后程序尝试调用 addCube() 失败,我不知道为什么,因为这段代码工作正常(只需更改第三行):

cubeBox temp(bx,by,bz);
cubeBoxData.insert(temp);
set<cubeBox>::iterator i = find(cubeBoxData.begin(),cubeBoxData.end(),temp);
const_cast<cubeBox&>(*i).addCube(x,y,z);

cubeBox 的运算符<为:

bool operator<(const cubeBox& c) const {
    return x<c.x ? true : y<c.y ? true : z<c.z ? true : false;
}

addCube 不会改变 x、y 或 z。

我认为我的操作员<错了,我错过了一些愚蠢的东西,但我不知道它是什么。

C++

评论

0赞 Kerrek SB 1/12/2013
非常仔细地考虑您的比较运算符:首先尝试二维操作。确保您了解比较运算符的要求。阅读文档和手册,直到您理解这些内容。
2赞 sdkljhdf hda 1/12/2013
哇!算子<滥用三元算子。我建议重构它: return x < c.x ||y < c.y ||Z<C.Z;
0赞 Mankarse 1/12/2013
@lego:这种重构是不正确的,因为它不会建立严格的弱排序(可能存在一个 和 使得两者都 和 )。aba < bb < a
1赞 Mankarse 1/12/2013
这也是非常值得怀疑的。在其下执行的操作不得更改元素的排序顺序。const_cast
1赞 sdkljhdf hda 1/12/2013
@Mankarse,重构是正确的,因为它计算的值与原始代码相同。如果我建议的重构更改为不再重构,那将是一个错误修复。而且我不是在提出错误修复。

答:

5赞 Mankarse 1/12/2013 #1

您定义的 不会建立严格的弱排序。例如,根据您的比较器,它既是 that 又是 that .因此,对 的所有操作都具有未定义的行为。operator<{1,0,1} < {0,1,0}{0,1,0} < {1,0,1}set

您应该重写比较操作,以便它确实建立严格的弱排序。最简单的方法是使用:std::tuple

bool operator<(const cubeBox& c) const {
    return std::tie(x,y,z) < std::tie(c.x,c.y,c.z);
}

评论

0赞 Mankarse 1/12/2013
如果您不能使用 std::tie,请记住 boost::tie 是一个有效的替代方法。
0赞 Josu Goñi 1/12/2013
谢谢,你是对的!问题是当 x>c.x 它应该返回 false 并停止检查时,我认为这应该更好:返回 x<c.x ?真 : x>c.x ?错误 : y<c.y ?真 : y>c.y ?错误:z<c.z ?true : 假;const cast 是因为“cubeBox”包含“立方体”的向量,也许我应该使用地图,但我没有改变短,我只是填充了那个向量。
1赞 Mankarse 1/12/2013
@JotaGe:为了正确起见,手动版本必须按如下方式工作:.return x == c.x ? (y == c.y ? (z < c.z) : (y < c.y)) : (x < c.x)
0赞 sbabbi 1/12/2013 #2

要整合前面的答案:

集合的元素是常量是有原因的,你不能只是const_cast和修改,因为这样做并不是告诉集合它应该重新排序你的元素。由于您的函数可能会更改元素的排序顺序,因此正确的方法是:addCube

cubeBox cpy = *i;
cubeBoxData.erase(i);
cpy.addCube(x,y,z);
cubeBoxData.insert(cpy);

评论

0赞 Josu Goñi 1/12/2013
正如我所写的,我没有改变顺序,x、y 和 z 仍然保持不变。问题出在我的.operator<
0赞 sbabbi 1/12/2013
@JotaGe很抱歉,所以错过了那句话