在实例变量中定义字段会导致所有实例字段相同

时间:2015-06-30 16:06:13

标签: c++

免责声明:我刚刚学习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());
}

我真的不明白为什么会这样。非常感谢任何帮助。

2 个答案:

答案 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;数。要解决此问题,请将随机数生成器设置为静态变量,使其保留在内存中,而不是每次使用时重新播种。