为用户定义 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,希望会出现段错误。
我有一个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,希望会出现段错误。