在引用这些指针时,我是如何意外覆盖的?

时间:2009-02-13 05:37:21

标签: c++ pointers

今晚最后一个问题,我保证。这些指示让我头痛不已。

我有一个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被声明为引用,但如果我尝试将其设置为其他内容,则会出现编译错误。

5 个答案:

答案 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)方法,如果这样可以让你的生活更轻松。

如果您担心函数调用的开销,可以内联。