更新:请注意,由于我需要一行支持多个操作(将在python中使用),因此我被迫返回指向结果的指针
今天,我在编程生涯中遇到了最困难的问题,所以我希望有人能提供帮助。
在graph_p.h
中,我有:
typedef struct Graph* Graph_P;
(Graph_P是图形的指针)
Graph
是我定义的另一个类
在graph_p.cpp
中,我具有以下功能:
Graph_P create()
{
try {
Graph_P graph=new Graph;
return graph;
}
catch (std::bad_alloc &) {
std::cout << "Error: Allocation Failed" << std::endl;
return nullptr;
}
}
void destroy(Graph_P graph_p)
{
delete graph_p;
}
以及以下graphUnion
函数(这是我们的主题):
Graph_P graphUnion(Graph_P graph_in1, Graph_P graph_in2, Graph_P graph_out) {
try {
*graph_out=(*graph_in1)+(*graph_in2);
//I have defined operator + between two graphs which returns a new graph built using default c'tor **not using new**
destroy(graph_out);
return graph_out;
}
catch (CException::exception &e) {
std::cout << e.what() << std::endl;
return nullptr;
}
}
出了什么问题?
如果operator +
失败,我将删除graph_out
的内容,这是不应该的。
建议的解决方案:
像这样在临时graph_out
对象中保存Graph_P
内容:
Graph_P graphUnion(Graph_P graph_in1, Graph_P graph_in2, Graph_P graph_out) {
try {
Graph tmp=*graph_out;
tmp=(*graph_in1)+(*graph_in2);
destroy(graph_out);
graph_out=&tmp;
return graph_out;
}
catch (CException::exception &e) {
std::cout << e.what() << std::endl;
return nullptr;
}
}
出了什么问题?
我正在将一个不是通过new
分配的值放入graph_out内,因此,如果用户在函数外键入destroy(graph_out)
,那将是未定义的操作,因为我读到:
您只需要delete
new
我该如何解决?
答案 0 :(得分:2)
typedef struct Graph* Graph_P;
这是一个坏主意。应该避免混淆这样的指针。
问题在这里:
Graph tmp=*graph_out;
// ...
graph_out=&tmp;
return graph_out;
您将创建一个局部于函数的图形。函数返回时,它将自动销毁。您返回一个指向该图的指针。返回的指针将在函数外部无效。尝试通过该悬空指针删除或访问不存在的值会导致行为不确定。
答案 1 :(得分:-3)
我认为最简单的解决方案是在 destroy()函数中添加if语句,以确保graph_p不是nullptr:
void destroy(Graph_P graph_p)
{
if (graph_p != nullptr) {
delete graph_p;
}
}
我认为将Graph_P用作智能指针(如果您至少使用C ++ 11)将是一个好主意-内存分配会更容易。