【问题标题】:Genetic Algorithm & Neural Networks: taking address of temporary [-fpermissive]遗传算法和神经网络:获取临时地址 [-fpermissive]
【发布时间】:2015-05-09 19:20:27
【问题描述】:

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

获取临时地址[-fpermissive]

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

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

主要问题在于变量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);
         }
    }
}

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

非常感谢您帮助解决问题...如果您需要更多信息,请告诉我。

【问题讨论】:

  • “C++ 标准不允许获取临时对象的地址” 你的意思是堆栈上的对象?您可以获取这些地址;在函数返回后它们将不再有效。此外,没有人会克隆您的项目;请在问题本身中包含MCVE
  • 你在哪里删除l?使用智能指针。
  • @Neil Kirk:感谢您强调智能指针。我将使用智能指针...因为这是我正在修改为当前 C++11 标准的旧代码...

标签: c++ neural-network genetic-algorithm temporary-objects


【解决方案1】:

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

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

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

这里有一个 getter (getm_vListofSynaptics()),它返回一个临时值:公共数据成员 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?)。

您必须考虑/应用一些更改:

  • getter/setter 对于封装行为/隐藏属性的内部表示很有用 (?),但 m_vListofSynaptics 是公开的,因此 getter “几乎什么都不买”(例如,参见 Why use getters and setters? / @ 987654323@ 了解一些见解)

  • 关于错误,您可以(这只是一个“快速修复”,似乎可以更改设计以完全避免 getter):

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

      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?

【讨论】:

  • 非常感谢,它解决了我的问题。我更喜欢使用 getter 函数的第一个解决方案。但是又出现了一个错误。它带有在 main.cpp 中实现的 GetID()。我如何使它适用于所有课程,例如在克莱尔。这不是单个文件编码的问题,但由于我在多个文件中有类,所以我需要他们可以访问这个函数。我应该让它全球化(但我不知道如何)。
  • ...或将static 计数器直接添加到CNeuron / CLayer / CSynapticConnection 类(使用相应的get() 方法)。
猜你喜欢
  • 2019-04-15
  • 2010-10-24
  • 2011-06-30
  • 1970-01-01
  • 2017-10-25
  • 2013-05-05
  • 2018-10-22
  • 2011-07-04
  • 2011-01-06
相关资源
最近更新 更多