遗传算法和神经网络:获取临时地址 [-fpermissive]

Genetic Algorithm & Neural Networks: taking address of temporary [-fpermissive]

我正在研究基因进化的神经网络。我在 2008 年使用 visual studio 2005 编写了一个程序。现在我将该程序转换为支持 c++11 的 Eclipse(Linux) 和 VS 2013(Win) 项目。在 运行ning 之后,两个项目都给出了相同的错误:

taking address of temporary [-fpermissive]

经过大量搜索后,我发现这个错误是由于新的 C++ 标准不允许获取临时对象的地址而产生的。由于所有对象都是使用 "new" 创建的(所以我想它们应该一直可用)。我部分地解决了问题,但不知道如何解决。如果您 运行 eclipse 项目,它只会突出显示项目中的两个错误。

因为它需要完整的代码来检查,所以很难用语言解释,所以我在 git 上的 https://bitbucket.org/a-akram/geans.git 上托管了 eclipse 项目,我让每个人都可以访问它。

主要问题是变量 wp1wp2m_vPopulatin 是一个包含神经网络地址的向量。

CNeuralNetwork* CGeneticEngine::Evolve()
{
    CLearningEngine *l;
    double totalError =  0.0;
    for (int iter = 0;iter < CGN_MAXITER; iter++)
    {
        for (int i = 0;i < CGN_POPULATION; i++)
        {
            l = new CLearningEngine(m_vPopulation[i]);
            l->Run(m_vTrainingDataset);
            for(unsigned int p = 0; p < m_vTrainingDataset->size(); p++)
            {
                totalError = totalError + m_vPopulation[i]->getm_dTotalNetworkError();
                totalError = totalError/m_vTrainingDataset->size();
            }
            if (totalError < CGN_THRESHOLD)
                 return m_vPopulation[i];

            m_dErrors[i] = totalError;
        }
        SortFitnesses();
        NewPopulation();
    }
    return NULL;

}

void CGeneticEngine::NewPopulation()
{
    int id1, id2;
    double temp;
    std::vector <CSynapticConnection *> *wp1;
    std::vector <CSynapticConnection *> *wp2;
    for (int i=0;i<CGN_POPULATION / 2;i++)
    {
        id1 = rand() % CGN_POPULATION / 2;
        id2 = rand() % CGN_POPULATION / 2 + CGN_POPULATION / 2;

        wp1 = &m_vPopulation[id1]->getm_vListofSynaptics();
        wp2 = &m_vPopulation[id2]->getm_vListofSynaptics();

        // Cross over the weights.
        for (int j = 0; j < 2; j++)
        {
            temp = (*wp1)[j+6]->getWeight();
            (*wp1)[j+6]->setWeight((*wp2)[j+6]->getWeight() );
            (*wp2)[j+6]->setWeight(temp);
        }

        //  adding slight genetic change due to crossover randomly.
        if (rand() % 10 < 2)
        {
            for(unsigned int j = 0; j < wp1->size();j++)
                (*wp1)[j]->changeWeight((double)(rand())/(32767/2) - 1);

            for(unsigned int j = 0; j < wp2->size();j++)
                (*wp2)[j]->changeWeight((double)(rand())/(32767/2) - 1);
         }
    }
}

因为这是我在这个论坛上的第一个问题所以我可能措辞不当所以我请求版主暂时不要关闭它。如有必要,我会说得更清楚。但是有了项目文件在手,你们就很容易找出问题和解决方案了。

非常感谢您帮助解决问题...如果您需要任何进一步的信息,请告诉我。

首先考虑 CNeuralNetwork class 的这个子集:

class CNeuralNetwork
{
  // ...
public:
  std::vector<CSynapticConnection *> getm_vListofSynaptics()
  {
    return m_vListofSynaptics;
  }

  std::vector<CSynapticConnection*> m_vListofSynaptics;
  // ...
};

这里有一个 getter (getm_vListofSynaptics()) returns 一个临时值: public 的 copy数据成员 m_vListofSynaptics.

CGeneticEngine::NewPopulation() 函数中,您正在获取临时对象的地址,这会触发错误:

wp1 = &m_vPopulation[id1]->getm_vListofSynaptics();
wp2 = &m_vPopulation[id2]->getm_vListofSynaptics();

(有关详细信息,请参阅 Why is taking the address of a temporary illegal?)。

您必须进行一些更改 consider/apply:

  • getters/setters 对于封装行为/隐藏 属性 的内部表示很有用(?)但是 m_vListofSynaptics 是 public 所以getter "buys you next to nothing"(例如,请参阅 Why use getters and setters? / Public Data members vs Getters, Setters 了解一些见解)

  • 关于这个错误,你可以(这只是一个"quick-fix",貌似可以改一下设计,完全避免getter):

    • 更改 getter 使其 returns 指向数据成员的引用/指针(数据成员应该是私有的)

      class CNeuralNetwork
      {
      // ...
      public:
        std::vector<CSynapticConnection *> *getm_vListofSynaptics()
        {
          return &m_vListofSynaptics;
        }
      private:
        std::vector<CSynapticConnection*> m_vListofSynaptics;
      };
      
    • 直接访问 m_vListofSynaptics 数据成员(可能不是一个好主意):

      wp1 = &m_vPopulation[id1]->m_vListofSynaptics;
      

      (看看If a variable has getter and setter, should it be public?)