【问题标题】:C++ exception thrown抛出 C++ 异常
【发布时间】:2021-08-15 16:49:37
【问题描述】:

我正在学习 C++,并且已经浪费了相当长的时间来尝试解决我遇到的错误的原因。 当我运行下面的代码时,我抛出了一个异常。它发生在程序结束时,所以我认为它与 Edge 指针有关:

#include <iostream>
#include <vector>
#include <map>

using namespace std;


struct Edge {
    int src, dest;
};

class Graph {
    
public:
    int V, E;
    Edge *edge = new Edge[E * sizeof(Edge)];
    Graph(int Ver, int Edg);
};

Graph::Graph(int Ver, int Edg) {
    V = Ver;
    E = Edg;
}


Graph* createGraph(int V, int E) {

    Graph* graph = new Graph(V,E);
    return graph;
}

int find(int* parents, int val) {
    if (parents[val] == -1)
        return val;
    return find(parents, parents[val]);
}

void Union(int *parents, int x, int y) {
    parents[x] = y;
}


int isCycle(Graph* graph) {

    int* parents = new int[graph->V * sizeof(int)];

    memset(parents, -1, graph->V * sizeof(int));

    for (int i = 0; i < graph->E; i++) {
        int x = find(parents, graph->edge[i].src);
        int y = find(parents, graph->edge[i].dest);

        if (x == y) {
            return 1;
        };

        Union(parents, x, y);
    }


    return 0;
}



int main()
{

    int V = 9, E = 8;
    Graph* graph = createGraph(V, E);


    graph->edge[0].src = 0;
    graph->edge[0].dest = 1;

    graph->edge[6].src = 0;
    graph->edge[6].dest = 6;

    graph->edge[5].src = 0;
    graph->edge[5].dest = 7;

    graph->edge[1].src = 1;
    graph->edge[1].dest = 2;

    graph->edge[2].src = 3;
    graph->edge[2].dest = 2;

    graph->edge[3].src = 4;
    graph->edge[3].dest = 3;

    graph->edge[4].src = 4;
    graph->edge[4].dest = 5;

    graph->edge[7].src = 5;
    graph->edge[7].dest = 7;

    if (isCycle(graph))
        cout << "graph contains cycle";
    else
        cout << "graph doesn't contain cycle";

    return 0;
}

我几个月前才开始学习 C++,谁能帮我理解为什么会出现这个异常?

【问题讨论】:

  • 尝试调试你的代码。
  • 在执行new Edge[E * sizeof(Edge)] 时,E 尚未初始化。因此,该程序表现出未定义的行为。
  • 感谢伊戈尔,你是绝对正确的!初始化边缘 = 新边缘 [边缘 * sizeof(边缘)];在构造函数中解决了问题。
  • 我建议避免使用指针,除非您只需要指向某些东西。你的createGraph 不应该存在——调用者可以只使用构造函数:Graph graph(V, E);edge(更喜欢集合的复数形式)可以简单地使用 std::vector&lt;Edge&gt; 来修复每个 Graph 对象中的内存泄漏。 parents 又可以是std::vector&lt;int&gt;——你在那里泄漏了更多的内存。指针参数可能是引用,因为您假设它们不为空,如果您不修改它们,它们可以是 const

标签: c++ exception


【解决方案1】:
 Edge *edge = new Edge[E * sizeof(Edge)];

除非 E 被初始化,否则这会将未初始化的变量乘以 sizeof(Edge)(这在其表面值上也是错误的,但我们稍后会讨论)。这是未定义的行为。

Graph::Graph(int Ver, int Edg) {
    V = Ver;
    E = Edg;
}

这还不够好。类成员的默认值(如果指定)用于在构造函数的主体开始运行之前初始化它们。

正确的方法是使用构造函数的初始化部分

Graph::Graph(int Ver, int Edg) : V{Ver}, E{Ver}
{
}

这首先初始化VE,所以现在:

Edge *edge = new Edge[E * sizeof(Edge)];

所以在这里,E 现在已经初始化,解决了这个问题。但这仍然有点不正确。很明显,根据其余代码,这确实应该是:

Edge *edge = new Edge[E];

在 C++ 中,当您希望声明一个由 4 个整数组成的数组时,您所要做的就是声明:

int n[4];

编译器负责将 4 乘以保存 int 所需的字节数。 new 语句也是如此。如果你的目标是构建一个#EEdges 的数组,那么毫无疑问就是:new Edge[E]。同样的错误在所示代码中多次出现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-01
    • 2015-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-24
    • 2010-09-13
    相关资源
    最近更新 更多