为用户定义 class 正确调用复制构造函数/赋值运算符

Invoking copy constructor/ assignment operator properly for user defined class

我有一个classPoint如下图:

class Point
{
    int x_v = {-1};
    int y_v = {-1};
    int val_v = {0};
    double f_v = {1000000};
    double g_v = {1000000};
    double h_v = {1000000};
    Point* parent_v = nullptr;
public:
    Point(){}
    Point(int x, int y, int val) : x_v{x}, y_v{y}, val_v{val}
    {}
    Point(const Point& p1)
    {
        x_v = p1.x();
        y_v = p1.y();
        val_v = p1.val();
        f_v = p1.f();
        g_v = p1.g();
        h_v = p1.h();
        *(parent_v) = *(p1.parent());
    }
    ~Point(){}

    int val() const
    {
        return val_v;
    }

    int x() const
    {
        return x_v;
    }

    int y() const
    {
        return y_v;
    }

    double f() const
    {
        return f_v;
    }

    double g() const
    {
        return g_v;
    }

    double h() const
    {
        return h_v;
    }

    Point* parent() const
    {
        return parent_v;
    }

    void set_g(double g)
    {
        g_v = g;
        f_v = g_v + h_v;
    }

    void set_h(double h)
    {
        h_v = h;
        f_v = g_v + h_v;
    }

    void set_parent(Point* p)
    {
        parent_v = p;
    }

    Point& operator=(const Point& p1)
    {
        x_v = p1.x();
        y_v = p1.y();
        val_v = p1.val();
        f_v = p1.f();
        g_v = p1.g();
        h_v = p1.h();
        *(parent_v) = *(p1.parent());
        return *this;
    }

    friend bool operator<(const Point& p1, const Point& p2)
    {
        return p1.f() < p2.f();
    }

    friend bool operator==(const Point& p1, const Point& p2)
    {
        std::cout << p1.g() << "\t" << p2.g() << "\n";
        return (p1.x() == p2.x()) && (p1.y() == p2.y()) && (p1.g() == p2.g());
    }

    friend bool operator!=(const Point& p1, const Point& p2)
    {
        return !(p1 == p2);
    }
};

在后面的代码部分,有:

std::set<Point> frontier;
frontier.insert(start_v);
start_v.set_g(0);
std::cout << "start g: " << start_v.g() << "\n";
start_v.set_h(this -> manhattan(start_v));
while(!frontier.empty())
{
    Point curr_point = *(std::min_element(frontier.begin(), frontier.end()));
    std::cout << "curr_point g: " << curr_point.g() << "\n";
    /* Other code */
}

创建复制构造函数和赋值运算符的原因是为了确保上述代码块的 while 循环内的行:Point curr_point = *(std::min_element(frontier.begin(), frontier.end())); 正常工作。

class Point 被另一个名为 Astar 的 class 使用:

class Astar
{
    std::vector<std::vector<Point>> map_v;
    int map_x = {0};
    int map_y = {0};
    Point start_v;
    Point end_v;
    std::vector<Point> path_v;
public:
    Astar(std::vector<std::vector<int>>&, std::pair<int, int>&, std::pair<int, int>&);
    bool is_valid(int, int);
    double manhattan(Point&);
    void search();
    std::vector<Point> path();
};

其构造函数:

Astar::Astar(std::vector<std::vector<int>>& map, std::pair<int, int>& start, std::pair<int, int>& end)
{
    map_y = map.size();
    if(map_y)
    {
        map_x = map[0].size();
    }
    if(map_x == 0 || map_y == 0)
    {
        throw std::invalid_argument{"The map is invalid!\n"};
    }
    for(int i = 0; i < map_y; i++)
    {
        map_v.push_back(std::vector<Point>(map_x));
        for(int j = 0; j < map_x; j++)
        {
            map_v[i][j] = Point(j, i, map[i][j]);
        }
    }
    start_v = Point(start.second, start.first, map[start.first][start.second]);
    end_v = Point(end.second, end.first, map[end.first][end.second]);
    if(!is_valid(start_v.x(), start_v.y()))
    {
        throw std::out_of_range{"Start point is out of range!\n"};
    }
    if(!is_valid(end_v.x(), end_v.y()))
    {
        throw std::out_of_range{"End point is out of range!\n"};
    }
}

问题是程序在尝试 运行 时终止。当我 运行 调试器时,程序在以下行终止:

map_v[i][j] = Point(j, i, map[i][j]);

这是在添加了Point的复制构造函数和赋值运算符之后开始的。在这种情况下,我无法确定确切的问题。请帮忙。

编辑:

自从问题的方向改变并且回答了原始问题后,所有之前的编辑都已删除。

这条语句map_v[i][j] = Point(j, i, map[i][j]);是你麻烦的根源。让我们稍微分析一下。

Point(j, i, map[i][j]) Creates a temporary object of type Point 
                       at this point, due to the Point constructor
                       member variable parent_v is nullptr
map_v[i][j] = ....     This uses the overloaded assignment operator. 
                       Go to its definition and at the end you will see 
                       *(parent_v) = *(p1.parent());

所以语句 p1.parent() 将产生 nullptr。取消引用是 UB,希望会出现段错误。