所以我的代码出了问题。我想将指针数组中的值传递给函数,这样原始对象就不会受到干扰。 (如果我通过参考,我的代码工作得非常好;我只是尝试以不同的方式进行学习练习)。实现返回后,我收到一个错误:
"对象0x100105790的错误:未分配被释放的指针 ***在malloc_error_break中设置一个断点来调试"。
我知道这是因为当函数返回时值超出范围,对象调用析构函数但我的析构函数假定已分配的指针,因此错误。我很好奇是否有办法测试基因组是否已经分配。如果不是我会为析构函数做其他事情?这是否是一个值得烦恼的问题,因为我已经通过传递参考工作了?该功能实际上并不具有破坏性;我只是想做一些技巧。我不喜欢走简单的路。
//class destructor for int genome[]
Organism::~Organism() {
//cout << "Deleting this: " << this << endl;
if (this->genome != NULL) {
delete [] this->genome;
}
}
//declare genome pointer
int *genome;
/**
* Default constructor for class
*/
Organism::Organism() {
this->fitness = 0;
this->size = 0;
this->genome = NULL;
}
//another constructor for if only the size of genome is defined
Organism::Organism(int size) {
this->fitness = 0;
this->size = size;
this->genome = new int[size];
}
//another constructor for when all starting values are defined
Organism::Organism(int size, int *genome) {
this->fitness = 0;
this->size = size;
this->genome = new int[size];
for (int i = 0; i < size; i++) {
this->genome[i] = genome[i];
}
}
//initialize and populate reproducible from already existing array start_pop (this has been verified as being properly allocated and values initiated)
vector<Organism*> reproduceable (0);
for (int i = 0; i < start_pop.size(); i++) {
if (start_pop[i]->get_fitness() > threshold) {
reproduceable.push_back(start_pop[i]);
}
}
//function definition
Organism* reproduce(Organism, Organism);
//function call in main()
offspring.push_back(reproduce(*reproduceable[i], *reproduceable[i+1]));
//function implementation
Organism* reproduce(Organism a, Organism b) {
int genome[4];
//randomly decide on where to split parent genomes
int split = rand() % 5;
for (int i = 0; i < a.get_size(); i++) {
if (i < split) {
genome[i] = a.get_genome()[i];
} else {
genome[i] = b.get_genome()[i];
}
}
//now cause random mutation in 2% of the population
if ((rand() % 100 + 1) <= 2) {
int rand_index = rand() % 5;
int mutation = rand() % 6 + 1;
genome[rand_index] = mutation;
}
Organism *child = new Organism(4, genome); //need to add genome
return child;
}
编辑为可重现的
添加默认构造函数和数组初始化答案 0 :(得分:1)
你的问题在这一行:
offspring.push_back(reproduce(*reproduceable[i], *reproduceable[i+1]));
请注意,您将两个reproduceable
按值传递给函数。函数的签名是
Organism* reproduce(Organism a, Organism b)
它期望两个Organism
的值,这意味着对于Organism
两个都将调用复制构造函数。由于您没有定义复制构造函数,因此将创建一个默认的复制构造函数,只将一个生物体的内容复制到另一个生物体中,包括指向基因组的指针。问题是现在两个Organism
都将被释放 - 这个函数是本地的,并且是传递给它的那个,导致双重释放为基因组分配的内存。有两种方法可以解决它:
Organism* reproduce(const Organism &a, const Organism &b)
这样您的Organism
将不会被复制,因此不会被双重释放。 (基于你的问题,我假设你已经尝试过了,并对第二种解决方案感兴趣:))
Organism::Organism(const Organism& a)
{
this->fitness = a.fitness;
this->size = a.size;
this->genome = new int[this->size];
for (int i = 0; i < this->size; ++ i)
this->genome[i] = a.genome[i];
}
通过这种方式,当您将有机体传递到您的函数中时,将调用您的自定义复制构造函数,并且将单独分配函数本地有机体的genome
。
答案 1 :(得分:1)
三条规则
如果一个类需要用户定义的析构函数,那么用户定义的副本
它几乎是构造函数或用户定义的复制赋值运算符
当然需要这三个。
请参阅http://en.cppreference.com/w/cpp/language/rule_of_three
虽然更好的方法是规则为零,但是你接受了价值语义。
对于这个程序,它就像更改genome
成员一样简单
从int*
到int[4]
,std::array<int,4>
或std::vector<int>
(并删除析构函数)