Генетический алгоритм и нейронные сети: получение адреса временного [-fpermissive]

Я работаю над генетически развитыми нейронными сетями. Я написал программу с использованием Visual Studio 2005 в 2008 году. Сейчас я преобразовал программу в проекты Eclipse (Linux) и VS 2013 (Win) с поддержкой С++ 11. После запуска оба проекта выдали одну и ту же ошибку:

получение адреса временного [-fpermissive]

После долгих поисков я обнаружил, что эта ошибка возникает, поскольку новые стандарты C++ не позволяют брать адрес временного объекта. Поскольку все объекты создаются с использованием «новых» (поэтому я думаю, они должны оставаться доступными все время). Частично разобрался с проблемой, но не знаю как решить. Если вы запустите проект eclipse, он выделит только две ошибки в проекте.

Поскольку это сложно объяснить словами, так как для изучения требуется полный код, я разместил проект eclipse на git по адресу https://bitbucket.org/a-akram/geans.git, который я сделал доступным для всех.

Основная проблема связана с переменными wp1 и wp2. m_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);
         }
    }
}

Поскольку это мой первый вопрос на этом форуме, возможно, я не совсем корректно его сформулировал, поэтому прошу модераторов не закрывать его на данный момент. Я сделаю это более ясным, если это необходимо. Но с файлами проекта на руках вам, ребята, будет очень легко разобраться в проблеме и найти решение.

Я буду очень признателен за вашу помощь в решении проблемы... пожалуйста, дайте мне знать, если вам нужна дополнительная информация.


person Adeel    schedule 08.03.2015    source источник
comment
Стандарты C++ не позволяют брать адрес временного объекта Вы имеете в виду объект в стеке? Вы можете взять адрес тех; они просто не будут действительны после возврата функции. Также никто не собирается клонировать ваш проект; включите MCVE в сам вопрос.   -  person Colonel Thirty Two    schedule 08.03.2015
comment
Где вы удаляете l? Используйте умные указатели.   -  person Neil Kirk    schedule 09.03.2015
comment
@Neil Kirk: Спасибо, что выделили умные указатели. Я буду использовать интеллектуальные указатели... так как это старый код, который я изменяю в соответствии с текущим стандартом С++ 11...   -  person Adeel    schedule 09.03.2015


Ответы (1)


Сначала рассмотрим это подмножество класса CNeuralNetwork:

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

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

Здесь у вас есть геттер (getm_vListofSynaptics()), который возвращает временное значение: копию члена общедоступных данных m_vListofSynaptics.

В функции CGeneticEngine::NewPopulation() вы берете адрес временного объекта, и это вызывает ошибку:

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

(см. Почему использование временного адреса является незаконным? для получения дополнительной информации).

Есть некоторые изменения, которые вы должны рассмотреть/применить:

person manlio    schedule 09.03.2015
comment
большое спасибо, это решило мою проблему. Я предпочитаю ваше первое решение с использованием функции получения. но появилась другая ошибка. Это с GetID(), который реализован в main.cpp. Как я могу сделать его доступным для всех классов, например. в КЛэйере. Это не проблема с кодированием одного файла, но поскольку у меня есть классы в нескольких файлах, мне нужна эта функция, доступная для них. Должен ли я сделать его глобальным (но я не знаю, как). - person Adeel; 09.03.2015
comment
Вы можете взглянуть на Как вы определяете глобальную функцию в С++? - person manlio; 09.03.2015
comment
...или добавить счетчик static непосредственно в классы CNeuron / CLayer / CSynapticConnection (с соответствующим методом get()). - person manlio; 09.03.2015