我正在为一个旅行推销员类型的问题编写回溯方法的代码。因此,在每个点上,我都会为剩余的未访问点进行递归。
我无法使用除cout,cin,new和delete之外的任何库/函数(因此没有向量)。所以对于这个问题,我想跟踪到目前为止我访问过的所有点数。我正在使用动态布尔数组。所以我想将动态数组作为值传递给函数以跟踪它。
这是我迄今为止所尝试过的。 我试图将数组包装在一个结构中,但内存处理(删除)给出错误(分段错误)
typedef struct Barray{
bool* a;
int size;
Barray(int size) { a = new bool[size]; this->size = size; }
Barray(const Barray& in) {
if(a) delete[] a; // error
a = new bool[in.size];
this->size = in.size;
for (int i = 0; i < in.size; i++)
a[i] = in.a[i];
}
~Barray() { delete[] a; } // error
}barray;
这是我的递归函数调用
void find_mindist(barray visited, int dist_now, int cur_p) {
if (base condition)
{return ;}
for (int i = 0; i < n; i++) {
if (visited.a[i]) continue;
barray tdist = visited;
tdist.a[i] = true;
int ndist = dist_now + dist(points[cur_p], points[i]);
find_mindist(tdist, ndist, i);
}
return ;
}
所以我的问题是 -
delete
上面会出错?答案 0 :(得分:3)
问题是这是一个副本构造函数。因此,在输入时,a
未初始化(因此包含垃圾),因此delete
无效。
Barray(const Barray& in) {
if(a) delete[] a; // error
a = new bool[in.size];
this->size = in.size;
for (int i = 0; i < in.size; i++)
a[i] = in.a[i];
}
只需删除delete
行即可。此外,更喜欢初始化成员
而不是分配它们,所以:
Barray(const Barray& in)
: a(new bool[in.size])
, size(in.size) {
for (int i = 0; i < in.size; i++)
a[i] = in.a[i];
}
另外,请记住Rule of Three。您需要一个复制赋值运算符。最简单的是:
Barry& operator=(const Barray& in) = delete;
如果您尝试使用它,它只会强制编译错误!更好的是:
Barry& operator=(const Barray in) { // **NOTE** pass by value!
std::swap(this.a, in.a);
std::swap(this.size, in.size);
}
此版本提供强大的异常保证。您不能使用std::swap
,因此您必须自己编写,或者手工编写(您选择)。
最后,如果你发现自己要回到Barray,你应该写一个移动构造函数:
Barray(Barray &&in)
: a(in.a)
, size(in.size) {
in.a = nullptr;
}
这可以节省大量的复制费用!
答案 1 :(得分:3)
首先,本地访问信息的推荐方法不是对整个访问集合的无休止复制,而是mark->recurse->unmark
方法。无论你做什么,请为访问过的信息保留一个布尔数组,并根据需要更新其内容。
出现其他问题是因为您尝试删除复制构造函数中未初始化的指针。此外,赋值运算符也应该重载以避免不愉快的意外。但是如果你不再复制你访问过的信息,那么这一点非常重要。