2015-10-01 2 views
-2

У меня возникла проблема с назначением новых значений динамическому массиву int, который является переменной-членом данных класса IntersectionFlowRate(). Я могу инициализировать и распечатать значения массива внутри конструктора. Однако, когда я выхожу из конструктора в другой класс, а затем вызывается функция внутри класса IntersectionFlowRate(), проходящая в переменных, чтобы перезаписать начальные значения элемента данных, это приведет к ошибке сегментации. Я отлаживался, чтобы обнаружить, что перезапись массива вызывает ошибку seg. И даже попытка получить доступ к динамическому массиву в рамках одной из его функций приведет к сбою.Назначение переменной переменных динамического массива C++

Мой вопрос в том, как я могу изменить значения переменной-члена динамического массива int из одной из своих функций i.e setArrayElement (int index, int x).

Вот некоторые из моих кодов. Извините, если я не понимаю или что-то нелепое. Я застрял на этом часами.

#ifndef INTERSECTIONFLOWRATE_H 
    #define INTERSECTIONFLOWRATE_H 

    class IntersectionFlowRate 
    { 
    public: 
     IntersectionFlowRate(); 
     ~IntersectionFlowRate(); 
     void setFlowCycle(int index, int flow); 

    private: 
     int* m_flowRateMotorCycle; 

}; 
#endif 

в файле .h^

#include "IntersectionFlowRate.h" 
    #include <cstdlib> 
    #include <iostream> 
    #include <new> 

    using namespace std; 
    IntersectionFlowRate::IntersectionFlowRate() 
    { 
     const int SIZE = 4; //Constant for m_flowRates[] size 

     //DYNAMIC MEMORY DELETE LATER 
     m_flowRateMotorCycle = new int[SIZE]; 

     for(int i = 0; i < SIZE; i++){ 
      m_flowRateMotorCycle[i] = 0; 
      cout << m_flowRateMotorCycle[i] << endl; 
      cout << "WE GOT HERE" << endl; 
     } 
    } 

    void IntersectionFlowRate::setFlowCycle(int index, int flow){ 
     cout << "INDEX: " << index << endl; 
     cout << "FLOW: " << flow << endl; 

     m_flowRateMotorCycle[index] = flow; //seg fault is here 
    } 

У меня есть еще один класс, который создает указатель на объект IntersectionFlowRate(), а затем вызывает функцию setFlowCycle проходящее в двух ДЕЙСТВИТЕЛЬНО Интс. С помощью отладки я смог передать 0 и 3 функции setFlowCycle (0, 3) просто отлично и вывести эти переменные внутри функции.

#ifndef TRAFFICSIM_H 
    #define TRAFFICSIM_H 

    #include "IntersectionFlowRate.h" 

    using namespace std; 

    class TrafficSim 
    { 
    public: 
     TrafficSim(); //Default Constructor 
     TrafficSim(const char* file); //Constructor 
     ~TrafficSim(); //Destructor 


    private: 
     IntersectionFlowRate* m_flowRate; 
    }; 
    #endif 


    #include "TrafficSim.h" 
    #include "IntersectionFlowRate.h" 
    #include <iostream> 
    #include <string> 
    #include <fstream> 
    #include <cstdlib> 


    using namespace std; 

    TrafficSim::TrafficSim() 
    { 

     IntersectionFlowRate* m_flowRate = new IntersectionFlowRate(); 
     m_flowRate->setFlowCycle(0, 3); 

    } 

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

+2

Вы должны предоставить [MCVE] (http://stackoverflow.com/help/mcve). – MikeCAT

+0

Пример [минимальный] (http://stackoverflow.com/help/mcve) - это не код, в котором вы * думаете * проблема, это минимально возможный ** полный ** код, который реплицирует проблему. Я предполагаю, что у вас есть [правило 0/3/5] (http://en.cppreference.com/w/cpp/language/rule_of_three) нарушение. Опубликуйте полный пример. – user657267

+0

[Простой тест] (http://melpon.org/wandbox/permlink/zZktmhgtuwPpZVPf) не дал мне ошибку сегментации. Вы определили (и инициализировали его, если необходимо) 'm_flowRateCar' правильно? – MikeCAT

ответ

2

Вы настраиваете локальная переменная называется m_flowRate, а не переменная член m_flowRate вашего TrafficSim класса:

Вместо этого:

TrafficSim::TrafficSim() 
{ 
    IntersectionFlowRate* m_flowRate = new IntersectionFlowRate(); 
    m_flowRate->setFlowCycle(0, 3); 
} 

Это должно быть так:

TrafficSim::TrafficSim() 
{ 
    m_flowRate = new IntersectionFlowRate(); 
    m_flowRate->setFlowCycle(0, 3); 
} 

Но в целом ему не нужно указывать указатель. Это может быть объект-член в вашем классе. Это было бы сократить использование указателя немного:

class TrafficSim 
{ 
    public: 
     TrafficSim(); //Default Constructor 
     TrafficSim(const char* file); //Constructor 

    private: 
     IntersectionFlowRate m_flowRate; 
}; 

Тогда:

TrafficSim::TrafficSim() 
{ 
    m_flowRate.setFlowCycle(0, 3); 
} 

Что касается вашего вопроса о том, как включить использование std::vector в классе, вот пример кода из IntersectionFlowRate класса, переписанный с использованием vector:

Vector sample

Кроме того, еще один источник пробл ems заключается в том, что ваши классы не могут следовать за Rule of 3, когда у вас есть указатели на динамически выделенную память в вашем классе.

Использование std::vector позаботится об этом автоматически, но если вы настаиваете на использовании указателей, вам необходимо придерживаться указаний по указанной ссылке.

+0

Удивительно это исправлено. Огромное спасибо. По иронии судьбы, я прочел ответ за эти часы назад, но я настолько стеснен, что, наверное, пропустил это. – Toasty

0

Да, используйте std :: vector, это намного проще, и это шаблон, так что он также довольно быстро и работает любым типом (лучше всего подходит для примитивных типов или указателей на объекты), а также имеет проверку границ и другие полезные вещи.

Если вам нужен быстрый массив типа доступа, то вы можете использовать зЬй :: карту, которая связывает ключ со значением, например, так

std::map<UINT, YourClass*> m_mapIDs_to_YourClass; 

Когда вы впервые начать использовать СТЛ контейнеры они могут показаться немного странным , но через некоторое время вы не сможете обойтись без них, к счастью, они уже некоторое время являются частью стандарта C++.

Проверка границ обоих этих контейнеров может быть выполнена путем сравнения вашего итератора с mapYourMap.end(), если они равны, вы прошли последний элемент и пытаетесь получить доступ к данным через итератор, вызывают исключение. Пример станд :: вектор (если vecInt является вектором < Int>):

vector<int>::iterator it = vecInt.begind(); 
    if (it == vecInt.end()) return; // vector is empty 
    do { // runs through elememts until out of bound, useful for searching 
     i++ 
    while (it != vecInt.end()); 
+0

Рекомендовать расширять бит при проверке границ, потому что подавляющее большинство векторных вызовов не проводит проверку границ. [Единственное исключение, о котором я знаю, это 'at'] (http://en.cppreference.com/w/cpp/container/vector/at). – user4581301

+0

Нет, не автоматически, это было бы расточительно, но вы можете сделать этот вектор :: iterator it = vecType.begin(); она ++; if (it == vecType.end()); // прошло последний элемент –

+0

Я добавил информацию, достаточно ли я достаточно или должен добавить пример кода? –

Смежные вопросы