list :: sort更改值c ++

时间:2018-02-21 10:09:50

标签: c++ visual-studio sorting

我在c ++中编写了一个不起作用的简单算法。我发现当我从我自己制作的自定义类中排序指向对象的列表时,它们会发生变化。或者更准确地说,列表会更改为该类中的奇怪随机对象。

// ConsoleApplication45.cpp : Defines the entry point for the console application.
//


#include "stdafx.h"
#include <iostream>  
#include <map>
#include <list>
#include <math.h> 
using namespace std;  

class LocationNode;
class NodeMap;


class LocationNode
{
private:
    char name;
    int xLocation;
    int yLocation;
    //map<LocationNode*,int> neighbors;
    LocationNode* neighbors[100];
    int neighborWeight[100];
    int neighborCount; 
    LocationNode *previous;
    int score;

    int CalcDistance(LocationNode &dest)
    {
        return (int)sqrt(pow(dest.xLocation-xLocation,2) + pow(dest.yLocation-yLocation,2));
    }

public:
    int finalScore;

    bool operator<(LocationNode const& rhs) const
    {
       // Use whatever makes sense for your application.
       return (finalScore < rhs.finalScore);
    }
    bool operator==(LocationNode const& rhs) const
    {
       // Use whatever makes sense for your application.
       return (name == rhs.name && xLocation == rhs.xLocation && yLocation ==rhs.yLocation );
    }

    LocationNode(char name, int x, int y)
    {
        neighborCount = 0;
        this->name = name;
        this->xLocation = x;
        this->yLocation = y;
    }

    string GetPath()
    {
        if(previous!=NULL)
        {
            return string(1, name).append((*previous).GetPath());
        } else {
            return string(1, name);
        }
    }

    void Connect(LocationNode &other, int weight)
    {

        this->neighbors[neighborCount] = &other;
        this->neighborWeight[neighborCount] = weight;
    }

    void CalcScore(LocationNode &previous, LocationNode &dest)
    {
        int index = 0;
        for (int i = 0; i < neighborCount; i++)
        {
            if(neighbors[i] == &previous)
            {
                index = i;
            }
        }
        score = previous.score + neighborCount[&index];
        finalScore = previous.score + neighborCount[&index] + CalcDistance(dest);
    }
    void CalcNeighbors(LocationNode &dest)
    { 
        for (int i = 0; i < neighborCount; i++)
        {
            (*neighbors[i]).CalcScore(*this,dest);
        }

        /*for (pair<LocationNode,int> node : neighbors) 
        {
            node.first.CalcScore(*this,dest);
        }*/
    }

};

bool my_compare (LocationNode* a, LocationNode* b)
{
    return a->finalScore < b->finalScore;
}




class NodeMap 
{
private:
    static LocationNode& str;
    static LocationNode& dest;
    static LocationNode* node;
    static list<LocationNode*> nodes;
    static void loop(bool isFirst)
    {
        if(isFirst)
        {
            node = &str;
        }
        (*node).CalcNeighbors(dest);
        nodes.sort(my_compare);
        node = nodes.front();
    }
public:
    static string start()
    {
        Init();
        loop(true);
        while(node != &dest)
        {
            loop(false);
        }
        return dest.GetPath();
    }
    static void Init()
{
    nodes.clear();
    LocationNode A ('A',1,2);
    nodes.push_back(&A);
    LocationNode B ('B',7,1);
    nodes.push_back(&B);
    LocationNode C ('C',2,8);
    nodes.push_back(&C);
    LocationNode D ('D',4,3);
    nodes.push_back(&D);
    LocationNode E ('E',9,6);
    nodes.push_back(&E);
    LocationNode F ('F',1,2);
    nodes.push_back(&F);
    A.Connect(B,2);
    B.Connect(D,3);
    D.Connect(E,2);
    E.Connect(F,3);
    A.Connect(C,1);
    C.Connect(F,10);
    dest = F;
    str = A;
}
};

LocationNode& NodeMap::str =  *(new LocationNode('A',1,2));
LocationNode& NodeMap::dest = *(new LocationNode('F',1,2));
LocationNode* NodeMap::node =  &str;
list<LocationNode*> NodeMap::nodes;



int _tmain(int argc, _TCHAR* argv[])
{
    cout << &(NodeMap::start());
    cin.get();
    return 0;
}
排序之前

https://i.imgur.com/nqU4m0j.png

排序后

https://i.imgur.com/eo2U3EB.png

很抱歉,我无法直接在这里发布图片,但我没有足够的声誉。

3 个答案:

答案 0 :(得分:6)

您正在推送指向堆栈分配对象的指针。在这些对象超出范围之后,这些指针变得无效,因此您的nodes容器最终会出现一堆悬空指针。您应该使用指向堆分配对象的指针填充此容器,以使它们有效。并且不要忘记稍后删除它们或使用智能指针。或者,您可以按值存储列表中的对象。请注意,与std::vector不同,std::list在添加或删除新项目时不会使指向现有项目的指针无效。

list<LocationNode> nodes;
nodes.emplace_back('A', 1, 2);

答案 1 :(得分:3)

这样的行
LocationNode A = *(new LocationNode('A',1,2));

在堆栈上创建类型为LocationNode的对象。新操作在堆上创建一个新对象,该对象将复制到本地对象中(请参阅AB,...),然后泄露。

当您向nodes conatiner添加本地对象时,只要退出Init函数,nodes中包含的数据就会因任何目的而无法使用。

更改上面的行:

LocationNode* A = new LocationNode('A',1,2);

然后使用

将它们添加到列表中
nodes.push_back(A);

应该摆脱90%的问题。

答案 2 :(得分:2)

    LocationNode A = *(new LocationNode('A',1,2));
    nodes.push_back(&A);
你在这做什么?您在堆上创建了对象new LocationNode('A',1,2),然后将此对象的副本设为LocationNode A = *(new LocationNode('A',1,2));A为副本,并在init函数中创建为本地变量。您将局部变量对象的地址推送到nodes向量,但是当init函数结束时,所有本地对象都被删除,并且您有nodes悬挂指针 - 它们指向不具有的对象存在。 您可以更改为

LocationNode* A = new LocationNode('A',1,2);
nodes.push_back(A);

并记住删除所有动态分配的对象。