C++删除指针上的运算符,指针不归零

Saa*_*an. 1 c++ pointers null-pointer delete-operator

我正在尝试用C++实现有向图.然而,我无法用我的RemoveEdge功能,之后我打电话的功能和它使用上的指针delete运算符,并设置指针nullptr,它不归零功能范围之外.

我不确定我是否已经清楚地说明了我的问题,但也许一些代码会有所帮助.

Graph.h

template<class TVertex, class TEdge, class TWeight>
class Graph
{
protected:
    std::list<Vertex<TVertex, TEdge, TWeight>*>* _Vertices;
    std::list<Edge<TVertex, TEdge, TWeight>*>* _Edges;
public:
    Graph();
    int TotalVertices();
    int TotalEdges();
    std::list<Vertex<TVertex, TEdge, TWeight>*>* Vertices();
    std::list<Edge<TVertex, TEdge, TWeight>*>* Edges();

    Vertex<TVertex, TEdge, TWeight>* FindVertex(const TVertex&);
    Vertex<TVertex, TEdge, TWeight>* InsertVertex(const TVertex&);
    void RemoveVertex(const TVertex&);

    Edge<TVertex, TEdge, TWeight>* FindEdge(const TEdge&);
    Edge<TVertex, TEdge, TWeight>* InsertEdge(const TVertex&, const TVertex&, const TEdge&, const TWeight&);
    void RemoveEdge(const TEdge&);
};
Run Code Online (Sandbox Code Playgroud)

Graph.FindEdge()

template<class TVertex, class TEdge, class TWeight>
Edge<TVertex, TEdge, TWeight>* Graph<TVertex, TEdge, TWeight>::FindEdge(const TEdge& label)
{
    Edge<TVertex, TEdge, TWeight>* edge = nullptr;
    std::list<Edge<TVertex, TEdge, TWeight>*>::iterator it;

    for(it = this->_Edges->begin(); it != this->_Edges->end(); ++it)
    {
        if(label == (*it)->Label())
        {
            edge = *it;
            break;
        }
    }

    return edge;
}
Run Code Online (Sandbox Code Playgroud)

Graph.RemoveEdge()

template<class TVertex, class TEdge, class TWeight>
void Graph<TVertex, TEdge, TWeight>::RemoveEdge(const TEdge& label)
{
    Edge<TVertex, TEdge, TWeight>* edge = this->FindEdge(label);
    if(edge == nullptr)
        return;

    this->_Edges->remove(edge);
    edge->Source()->RemoveEdge(edge);
    edge->Destination()->RemoveEdge(edge);

            // Problem is here, why isn't this working like I think it should?
    delete edge;
    edge = nullptr;
}
Run Code Online (Sandbox Code Playgroud)

Main.cpp的

// created graph
// added vertices
// added edges
Edge<string, string, int>* e5 = graph->InsertEdge("Oshawa", "Toronto", "E5", 5);
graph->RemoveEdge("E5");
cout << ((e5 == nullptr) ? "null" : "not null") << endl; // this outputs not null
Run Code Online (Sandbox Code Playgroud)

因此,当我从图中删除边缘后,您可以看到我的程序崩溃,由于某种原因,它not null在执行RemoveEdge函数后输出.我不确定为什么会发生这种情况,我已经使用了delete运算符,并且我之后也明确地将指针取消了.我在这做错了什么?

是的,我确定找到了边缘,FindEdge函数找到了正确的边缘对象并将其从相应的列表中删除,但删除操作符并没有按照我的意愿去做.

感谢任何帮助.提前致谢.

Naw*_*waz 5

e5是一个局部变量,它edge与类中的不同.

两者都可能指向内存中的同一个对象,并不意味着如果你创建一个null,另一个也会指向null.

考虑这个简单的例子,

int i = 10;
int *p1 = &i;
int *p2 = p1;

//here p1 and p2 points to the same object in memory which is i
p1 = nullptr; //it makes only p1 point to null

//here only p2 points to i
cout << *p2 << endl; //ok
cout << *p1 << endl; //dangerous - undefined behaviour!
Run Code Online (Sandbox Code Playgroud)

我希望这有助于您了解您的计划的行为!


但是,你可以做一件事.T*如果您使用T*&,而不是使用,那么您将得到预期的结果:

Edge<string, string, int>* & e5 = graph->InsertEdge("Oshawa", "Toronto", "E5", 5);
//                         ^ see this

graph->RemoveEdge("E5");
cout << ((e5 == nullptr) ? "null" : "not null") << endl;
Run Code Online (Sandbox Code Playgroud)

它应该工作,因为现在e5是对类中对象的引用,它不再是一个不同的对象,它更像是您创建并保存在列表中的指针的别名InsertEdge.

类似的代码中使用i,p1并且p2会是这样:

int i = 10;
int *p1 = &i;
int* & p2 = p1; //now it is a reference to p1, i.e an alias  of p1

//here p1 and p2 points to the same object in memory which is i

p1 = nullptr; //it makes only p1 point to null

//here both p1 and p2 points to null

 if ( p1 == nullptr)
       cout << "p1 points to null" << endl;
 if ( p2 == nullptr)
       cout << "p2 points to null" << endl;
 if ( p1 == p2)
       cout << "p1 and p2 are equal" << endl;
Run Code Online (Sandbox Code Playgroud)

输出:

p1 points to null
p2 points to null
p1 and p2 are equal
Run Code Online (Sandbox Code Playgroud)

演示:http://ideone.com/ARiIl

还要注意这些:

//after p1 = nullptr
cout << *p2 << endl; //dangerous - undefined behaviour!
cout << *p1 << endl; //dangerous - undefined behaviour!
Run Code Online (Sandbox Code Playgroud)

  • 在调用RemoveEdge之后,你需要非常小心,不要将e5作为悬挂参考. (2认同)