Компилируется нормально, но когда он достигает определенной точки, запуск завершается неудачно. Что я делаю не так?

#c #class #object #vector

#c #класс #объект #вектор

Вопрос:

Я создаю проект с обширным кодом, что является одной из приведенных ниже причин, по которым я не смогу опубликовать все это. Я создал пару классов, некоторые из которых дружат друг с другом. Теперь один из вариантов, который есть в этом проекте, — иметь возможность создавать несколько типов ландшафта, а затем вставлять объект в вектор класса «Continente», он делает это через цикл ниже.

 if(linhacomando[1] == "planicie"){
        
        for(int Ploop = 0; Ploop < quantidade; Ploop  ){
            
            Planicie P;
            C->AddPlanicie(amp;P);
            
        }
///more types of terrain with further "ifs" below, but posting it all would be too extensive
 

Итак, насколько я понимаю, это создает объект Planicie, который является этим классом.

 class Planicie{
    
private:
    
    string NomeP;
    const int ResistenciaP = 5;
    int CriarProdutoP;
    const int CriarOuroP = 1;
    const int PontosVitoriaP = 1;
    int ConquistadoP;
    
public:
 
    friend class Continente;
    friend class Imperio;
    friend class Mundo;
    static int NPlanicie;
    Planicie();
    
};
 

и этот конструктор

 int Planicie::NPlanicie = 0;

Planicie::Planicie(){
    
    NPlanicie  ;
    NomeP = "Planicie"   to_string(NPlanicie);
    CriarProdutoP = 1;
    ConquistadoP = 0;
    cout << NomeP << " criado." << endl;
    
}
 

Затем он сообщает объекту «C», который был создан выше (за пределами кода, размещенного здесь), чтобы добавить этот только что созданный объект в вектор, который имеет C, который использует эту функцию.

 void Continente::AddPlanicie(Planicie * P){
    
    VPlanicie.push_back(P);
    
}
 

и Continente (C) является этим классом

 class Continente{
    
private:
    
    vector <Planicie*> VPlanicie;
    vector <Montanha*> VMontanha;
    vector <Fortaleza*> VFortaleza;
    vector <Mina*> VMina;
    vector <Duna*> VDuna;
    vector <Castelo*> VCastelo;
    
public:
    
    friend class Mundo;
    void AddPlanicie(Planicie * P);
    void AddMontanha(Montanha *M);
    void AddFortaleza(Fortaleza *F);
    void AddMina(Mina *M);
    void AddDuna(Duna *D);
    void AddCastelo(Castelo *C);
    void ShowContinente();
    
};
 

Моя проблема заключается в следующем: теперь у меня есть команда, которая позволяет программе отображать все созданные до сих пор ландшафты, этот ландшафт хранится в соответствующих векторах Continente, но он не работает. Он компилируется нормально, имейте в виду, никаких ошибок вообще, затем я запускаю его, и я тоже могу создавать ландшафты просто отлично, в тот момент, когда я ввожу команду, чтобы показать, что было создано до сих пор, он просто отключается. Вот код.

 void Continente::ShowContinente(){
    
    for(int loop = 0; loop < this->VPlanicie.size(); loop  ){
        
        cout << this->VPlanicie[loop]->NomeP << endl;
        
    }
    
} /// at this moment I'm trying to only show all Planicie Terrains made so far, kinda like a test before adding the rest.
 

и вот функция, вызываемая в main

 void Lista(Continente * C){
   
    C->ShowContinente();
    
}

 

Например, допустим, я создал 3 объекта Planicie. Они должны быть равны [0][1][2] вектора VPlanicie, а затем, когда я попрошу его показать мне, он должен напечатать Planicie1, Planicie2, Planicie3.

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

Комментарии:

1. Вероятно, где-то неопределенное поведение. Время использовать отладчик.

2. Planicie P; C->AddPlanicie(amp;P); Вы храните адреса локальных переменных. Вы получаете висячие указатели, и возникает UB.

3. @churill поскольку это объект, он работает независимо? Потому что я создаю объект и сохраняю указатель на их ссылку внутри вектора?

4. @user215272 Вы создаете объект, сохраняете указатель на него, затем уничтожаете объект. Теперь указатель ни на что не указывает.

Ответ №1:

         for(int Ploop = 0; Ploop < quantidade; Ploop  ){
        
            Planicie P;
            C->AddPlanicie(amp;P);
        
        }
 

Таким образом, каждая итерация этого цикла создает экземпляр Planicie и передает его адрес AddPlanicie . Затем этот объект перестает существовать.

 void Continente::AddPlanicie(Planicie * P){

    VPlanicie.push_back(P);

}
 

О, вы только что добавили указатель на объект, который вот-вот перестанет существовать. Тогда этот указатель будет бесполезен.

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

Почему вы вообще используете указатели здесь? Почему бы не использовать векторы самих объектов? И если вы должны использовать указатели, используйте указатели, которые управляют временем жизни своих объектов, таких как std::unique_ptr или std::shared_ptr .

Комментарии:

1. Хорошо, итак, позвольте мне посмотреть, следую ли я, мой указатель в основном немного указывает на то, что было уничтожено, чтобы изменить это вместо создания объектов один за другим и указателей на них, я должен создать вектор объектов, а затем, если мне когда-нибудь понадобится добавить больше объектов позжеитерация просто добавляет их к этому вектору?

2. @user215272 Вы не можете добавить объект в вектор. Либо объект находится в векторе, либо нет. (То же самое относится и к массиву. Если i это целое число со значением 3, которого нет в векторе или массиве, если вы «добавляете i в вектор / массив», что вы на самом деле сделаете, это добавите значение 3 в вектор / массив.)

3. @user215272 Но вы можете создать вектор, который содержит экземпляры вашего класса, и вы можете создавать новые экземпляры в векторе. Но вы не можете буквально поместить существующий объект в вектор или извлечь объект из вектора — для этого вам придется создать новый объект.

4. @user215272 Если i равно 3, то вы «добавляете i к вектору», а затем устанавливаете i значение 4, вектор все равно будет содержать значение 3, потому i что его самого нет в векторе. Все, что вы сделали, это добавили новый объект с тем же значением, i что и . Если вам нужно буквально помещать объекты в вектор и из него, то в идеале вектор должен содержать какой-то указатель на этот объект std::unique_ptr<> .

5. итак, в качестве примера, если я делаю vector<test*> MyVector . Я могу хранить указатели на объекты типа test , однако, если я создаю тестовые объекты для какой-либо функции, выполняя Test test1 и т. Д., Как только я покидаю функцию, Объекты уничтожаются, и поэтому указатели MyVector ни на что не указывают, правильно?