免责声明:我刚刚学习C ++。另外,我不太确定如何说出问题的标题。我道歉。
问题: 所有GAChromosome在“染色体”载体中的实例最终都与最后一个GAChromosome实例相同的基因被推回到载体,尽管它们被不同的基因初始化。
问题: 为什么会发生这种情况?我该如何解决?
代码:
string generateRandomGenes(int theLength)
{
string genes = "";
for (int i = 0; i < theLength; i++)
{
int index = (rand() % kCharacterSet.length());
genes += kCharacterSet[index];
}
return genes;
}
GAPopulation::GAPopulation(int thePopulationSize, string theTargetGenes)
{
targetGenes = theTargetGenes;
chromosomes = vector<GAChromosome *>(thePopulationSize);
for (int i = 0; i < thePopulationSize; i++)
{
// These genes are different every time, which is correct.
string genes = generateRandomGenes((int)targetGenes.length());
GAChromosome * chromosome = new GAChromosome(genes);
chromosome->setFitness(calculateFitness(chromosome));
chromosomes.push_back(chromosome);
delete chromosome;
}
for (int i = 0; i < thePopulationSize; i++)
// Every instance has the same set of genes as the last chromosome inserted, which is incorrect.
printf("%s\n", chromosomes.at(i)->getGenes().c_str());
}
我真的不明白为什么会这样。非常感谢任何帮助。
答案 0 :(得分:7)
这是因为您的代码中有undefined behavior。
您为chromosome
分配内存,将指针推入向量,然后删除(释放)chromosome
指向的内存。释放内存会使所有指向内存的指针无效,包括向量中的指针。
通过一些插图来理解指针可能更容易。
分配内存时,它看起来像这样
+------------+ +---------------------------+ | chromosome | ---> | memory you have allocated | +------------+ +---------------------------+
将指针推入向量后,您现在必须指向向量:
+------------+ | chromosome | ---------\ +------------+ \ +---------------------------+ >--> | memory you have allocated | +-------------------+ / +---------------------------+ | pointer in vector | --/ +-------------------+
最后,当你释放内存时,它看起来像这样
+------------+ | chromosome | ---------\ +------------+ \ +-----+ >--> | ??? | +-------------------+ / +-----+ | pointer in vector | --/ +-------------------+
???
表示现在未分配的内存。
实际上可能发生的事情是,系统为下一次分配重用相同的内存,因此分配给chromosome
的下一个指针实际上指向同一个内存,并用新数据覆盖以前的内存。
创建循环结束后,内存实际上不再存在,其内容将是您写入该内存的最后一个数据,从而导致您看到的行为。
解决方法非常简单: 不要 使用指针。在现代C ++中,很少需要指针。而是将值存储在矢量,实际对象实例中,例如
vector<GAChromosome> chromosomes;
注意:如果GAChromosome
包含comples数据,那么您还应该了解rule of three/five/zero。
答案 1 :(得分:0)
Joachim Pileborg是对的;你有未定义的行为。一定要明白为什么会这样,因为这些错误往往会困扰新的C ++程序员。
可能会让你感到困惑的另一件事:generateRandomGenes(int)
功能。如果它每次创建一个新的随机数生成器,并且该生成器以系统时间(可能以毫秒为单位)播种,则该循环可能足够快地迭代,以便连续调用generateRandomGenes(int)
,系统时钟读取同一时间到毫秒,随机数发生器每次播种相同的种子,从而返回相同的随机数&#34;数。要解决此问题,请将随机数生成器设置为静态变量,使其保留在内存中,而不是每次使用时重新播种。