-1

ノードポインタのベクトルが2つあります。

vector<Node*> tmp; 

vector<Node*> nodes;

そして、私が言いますtmp = nodes;

私の場合delete nodes、それtmpも削除されます。

constにするなど、変更するtmpたびに変更しないようにする方法はありますか?nodes

私は基本的にダイクストラ法を実行しています。しかし、このアルゴリズムは最短経路を決定する際に常にノードベクトルを削除しました。つまり、送信元から宛先への最短パスは1回しか実行できません。

グラフがある場合0--->1 ---> 2 ---> 3 ie

CGraph g;

g.Dijkstras(0);
g.PrintShortestRouteTo(2);
g.Dijktras(2);         
g.PrintShortestRouteTo(3);    <-- source is still 0 since nodes is deleted
                                  therefore I get the path from 0 to 2


  class Node
{
public:
    Node(int id)
        : id(id), previous(NULL),
        distanceFromStart(INT_MAX)
    {
        nodes.push_back(this);
    }
public:
    int id;
    Node* previous;
    int distanceFromStart;
};

vector<Node*> nodes;

void CGraph::Dijkstras(int source)
{

    nodes[source]->distanceFromStart =  0;   


    for (int i = 0; i < (int)nodes.size(); i++)
        cout << nodes[i]->distanceFromStart << " " ;

    cout << "------------------------" << endl;

    while (nodes.size() > 0)
    {
        Node* smallest = ExtractSmallest(nodes);
        //cout << "Smallest: " << smallest->id << " ";
        //Node* smallest = nnodes[1];
        vector<Node*>* adjacentNodes =
            AdjacentRemainingNodes(smallest);
        const int size = adjacentNodes->size();
        for (int i=0; i<size; ++i)
        {
            Node* adjacent = adjacentNodes->at(i);
            int distance = Distance(smallest, adjacent) +
                smallest->distanceFromStart;
            if (distance < adjacent->distanceFromStart)
            {
                adjacent->distanceFromStart = distance;
                adjacent->previous = smallest;
            }
        }
        delete adjacentNodes;
    }
}
4

4 に答える 4

1

はポインターではないためdelete nodes、 と書くことはできません。nodesそれを書くと、コードはコンパイルされません。

これを書くとき:

vector<Node*> tmp = nodes;

次に、ベクターの内容ではなく、ベクター オブジェクトのコピーを作成します。ベクターの内容は、ベクターの両方のコピーで同じです。そのため、1 つのベクターの内容を変更すると、その変更はベクターの他のコピーにも反映されます。

コンテンツのコピーも作成する場合は、次のように記述します。

std::vector<Node*> tmp;
tmp.reserve(nodes.size()):

//include <algorithm> for std::transform
std::transform(nodes.begin(),   
               nodes.end(),
               std::back_inserter(tmp),
               [](Node const *node) { return new Node(*node); });

注:上記のコードは、ラムダ式を使用しているため、C++11 でのみコンパイルされます。C++03 では、その代わりに関数またはファンクターを使用できます。

の代わりにstd::unique_ptr<Node>またはなどのスマート ポインターを使用することを検討してください。スマート ポインターはメモリ自体を管理するため、それについて心配する必要があります。ただし、スマート ポインターを使用する場合、上記のコードは少し異なりますが、コンテンツのコピーを作成する場合の基本的な考え方は同じです。std::shared_ptr<Node>Node*

于 2012-06-07T05:22:02.990 に答える
0

あなたの質問は少し混乱していますが、私の解釈は次のとおりです。

std::vector<Node *> *tmp;
std::vector<Node *> *nodes;

nodes = somehow_gets_dynamically_created_vector();
tmp = nodes;
// perhaps do other things with nodes
delete nodes;

次に、コードはtmpぶら下がったままになります (つまり、解放されたメモリを指しています)。しかし。これは安全なはずです:

std::vector<Node *> tmp;
std::vector<Node *> *nodes;

nodes = somehow_gets_dynamically_created_vector();
tmp = *nodes;
// perhaps do other things with nodes
delete nodes;

さて、あなたのサンプルコードで、あなたが説明したものと漠然と似ている唯一のコードは、コードがadjacentNodes変数をどのように扱うかです。nodesそして、セリフが原因で何か悪いことが起こるのを集めますdelete adjacentNodes。私は、AdjacentRemainingNodes関数があなたが思っていることをしていることを確認します。少なくともnew std::vector<Node *>、その関数の本体内で実行されるコード内のどこかへの呼び出しによって提供される値を返す必要があります。そうでない場合、deleteonadjacentNodesは無効です。

しかし、おそらくあなたは別の意味を念頭に置いていたのでしょう。にコピーnodesした後tmptmpに更新された値が表示される場合distantFromStart、これはポインタを使用した結果です。ベクターでポインターを使用しないことで、この問題を回避できます。

std::vector<Node> tmp;
std::vector<Node> nodes;

tmp = nodes;

previousただし、コピー コンストラクターを定義するか、メンバーの処理方法を理解する必要があります。たとえば、コピー コンストラクターは、LHS から値をコピーするのではなく、単にpreviousメンバーを設定することができます。NULL

Node::Node (const Node &lhs)
    : id(lhs.id), previous(NULL), distanceFromStart(lhs.distanceFromStart)
 {}

しかし、適切なことは何でもするべきです。

于 2012-06-07T08:22:09.580 に答える
0

これを管理する 1 つの方法は、代わりに共有ポインターを使用することです。

vector<shared_ptr<Node> > tmp;

tmp/Nodes が他のオブジェクト (Node* が指しているオブジェクト) がまだ存在する前に範囲外になったとしても、そのようにします。

于 2012-06-07T05:23:10.050 に答える
0

ノードがクラスの場合は、ノードのコピーコンストラクターを実装する必要がある可能性があります。次に、「ノード」をループして、各アイテムを tmp にコピーします。

tmp.clear();

for(vector<Node*>::iterator it = nodes.begin(); it != nodes.end(); it++)
{
    Node* copy = new Node((*it));

    tmp.push_back(copy);
}
于 2012-06-07T05:24:24.240 に答える