我有两个节点指针向量。
vector<Node*> tmp;
vector<Node*> nodes;
我说tmp = nodes;
如果我delete nodes
,则tmp
也会被删除。
是否有任何方法可以在修改tmp
时修改nodes
,例如将其设为const?
我基本上是在经营Dijkstra的。但是该算法总是在确定最短路径时删除节点向量。这意味着我只能做一次从源到目的地的最短路径。
如果我有图0 ---&gt; 1 ---&gt; 2 ---&gt; 3 即
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;
}
}
答案 0 :(得分:1)
您无法编写delete nodes
,因为nodes
不是指针。如果你这样写,代码将无法编译。
当你这样写:
vector<Node*> tmp = nodes;
然后你制作一个矢量对象的副本,而不是矢量的内容。载体的两个拷贝中载体的含量相同。因此,如果您从一个向量更改内容,则更改也将反映在向量的另一个副本中。
如果你想复制内容,请写下:
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中编译,因为它使用lambda表达式。在C ++ 03中,您可以使用函数或函子。
考虑使用std::unique_ptr<Node>
或std::shared_ptr<Node>
等智能指针代替Node*
。智能指针管理内存本身,您需要担心它。但是,如果你使用智能指针,那么上面的代码会有所不同,但如果你想复制内容,基本的想法是一样的。
答案 1 :(得分:0)
管理此方法的一种方法是使用共享指针
vector<shared_ptr<Node> > tmp;
即使tmp / Nodes超出范围,另一个对象(Node *指向的对象)仍然存在。
答案 2 :(得分:0)
如果它是一个类,你可能需要为Node实现一个复制构造函数,然后遍历“nodes”以将每个项复制到tmp中
tmp.clear();
for(vector<Node*>::iterator it = nodes.begin(); it != nodes.end(); it++)
{
Node* copy = new Node((*it));
tmp.push_back(copy);
}
答案 3 :(得分: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 *>
所提供的值。如果没有,则delete
上的adjacentNodes
无效。
但也许你心中有不同的含义。相反,您的意思是在将nodes
复制到tmp
后,tmp
将更新后的值视为distantFromStart
,这是使用指针的结果。你可以通过不在向量中使用指针来避免这个问题。
std::vector<Node> tmp;
std::vector<Node> nodes;
tmp = nodes;
但是,您需要定义一个复制构造函数或以其他方式弄清楚如何处理previous
成员。例如,复制构造函数可以将previous
成员设置为NULL
,而不是复制LHS中的值。
Node::Node (const Node &lhs)
: id(lhs.id), previous(NULL), distanceFromStart(lhs.distanceFromStart)
{}
但是你应该做任何合适的事情。