今晚最后一个问题,我保证。这些指示让我头痛不已。
我有一个std :: list <Point
&gt;称为Polygon和std ::多边形列表,定义如下:
typedef std::list<Point> Polygon;
typedef std::list<Polygon> PolygonList;
// List of all our polygons
PolygonList polygonList;
我创建了下面的方法,试图从(x,y)中删除最近的Point,检查我的polygonList中的所有多边形。
void deleteNearestPoint(int x, int y)
{
y = screenHeight - y;
Polygon &closestPolygon = polygonList.front();
Polygon::iterator closestPoint = closestPolygon.begin();
float closestDistance = sqrt(pow(x - closestPoint->x, 2) + pow(y - closestPoint->y, 2));
// Search PolygonList
PolygonList::iterator listIter;
Polygon::iterator iter;
for(listIter = polygonList.begin(); listIter != polygonList.end(); listIter++)
{
Polygon &tempPolygon = *listIter;
for(iter = tempPolygon.begin(); iter != tempPolygon.end(); iter++)
{
const float distance = sqrt(pow(x - iter->x, 2) + pow(y - iter->y, 2));
if (distance < closestDistance)
{
closestPolygon = *listIter;
closestPoint = iter;
closestDistance = distance;
}
}
}
closestPolygon.erase(closestPoint);
redraw();
}
然而,在某个地方,我有一个指针或参考变量搞砸了我。这段代码编译但行为非常奇怪。
我编写了一个调试语句,假设我的多边形列表中有3个多边形,如下所示:
多边形#:0
点:(448,43)
要点:(469,177)
点:(374,123)
多边形#:1
点:(295,360)
点:(422,350)
要点:(315,266)
点:(295,360)
多边形#:2
点:(143,202)
要点:(301,203)
要点:(222,100)
要点:(143,202)
现在,让我说我尝试使用删除功能给它一个x / y接近点422,350所需的结果就是它只是从Polygon#1删除那个点(422,350)而是我得到这个:
多边形#:0
点:(295,360)
点:(422,350)
要点:(315,266)
点:(295,360)
多边形#:1
点:(295,360)
要点:(315,266)
点:(295,360)
多边形#:2
点:(143,202)
要点:(301,203)
要点:(222,100)
要点:(143,202)
它确实删除了(422,350),但它也有一个奇怪的副作用,即在删除其点之前将Polygon#0覆盖为Polygon#1。
我知道我的方法中使用的指针或引用不正确。有人可以指出我可能会做的是什么造成这种情况?我认为这是因为我的&amp; nearestPolygon被声明为引用,但如果我尝试将其设置为其他内容,则会出现编译错误。
答案 0 :(得分:6)
不幸的是,您无法重新绑定引用,即此行:
nearestPolygon = * listIter;
会将*listIter
复制到closestPolygon
,而不会将引荐重新绑定到*listIter
。
修改:要执行您想要的操作,您应该使用PolygonList::iterator
代替Polygon &
并相应地调整代码。
答案 1 :(得分:4)
其他答案指出了导致错误的原因。作为一般建议,我建议不要使用函数参数以外的引用。语义很混乱,对于那些试图阅读你的代码的人来说也是如此。尝试重写这样的东西(我没有测试代码):
void deleteNearestPoint(int x, int y)
{
y = screenHeight - y;
PolygonList::iterator closestPolygon = polygonList.begin();
Polygon::iterator closestPoint = closestPolygon->begin();
float closestDistance = sqrt(pow(x - closestPoint->x, 2) + pow(y - closestPoint->y, 2));
// Search PolygonList
PolygonList::iterator listIter;
Polygon::iterator iter;
for(listIter = polygonList.begin(); listIter != polygonList.end(); listIter++)
{
for(iter = listIter->begin(); iter != listIter->end(); iter++)
{
const float distance = sqrt(pow(x - iter->x, 2) + pow(y - iter->y, 2));
if (distance < closestDistance)
{
closestPolygon = listIter;
closestPoint = iter;
closestDistance = distance;
}
}
}
closestPolygon->erase(closestPoint);
redraw();
}
答案 2 :(得分:3)
您无法指定参考。
这是C ++中的引用和C#中的引用之间的主要区别。使用对象初始化引用变量后,该变量将成为该对象的别名。分配给引用变量等同于分配给原始对象。考虑到这一点,这一行:
closestPolygon = *listIter;
表示您使用当前多边形覆盖先前找到的最近多边形。这也与您获得的结果一致。 我建议您使用指针代替此方法的引用。
另外,正如其他人所指出的,使用pow(... , 2)
非常浪费。更好的是写下这样的东西:
x = a - b;
xsquare = x * x;
编辑:用指针编写这个将从类似的东西开始:
void deleteNearestPoint(int x, int y)
{
y = screenHeight - y;
Polygon *closestPolygon = &polygonList.front();
Polygon::iterator closestPoint = closestPolygon.begin();
答案 3 :(得分:2)
closestPolygon = *listIter;
将在引用指向的对象上调用operator =(),因此它将用第二个多边形覆盖第一个多边形。
将nearestPolygon声明为指针(即使在声明之后也可以指向不同的对象)
Polygon *closestPolygon = &(polygonList.front()); ... closestPolygon = &(*listIter);
答案 4 :(得分:1)
我看到你的问题已经得到了解答 - 我会把我的2美分投入,并建议你使用Point的方法来保存重复代码。
正如其他人所说,你可能也想要一个squareDistance(x,y)方法,如果这样可以让你的生活更轻松。
如果您担心函数调用的开销,可以内联。