【问题标题】:Compiles fine but when it reaches a certain point fails the run. What am I doing wrong?编译得很好,但是当它达到某个点时运行失败。我究竟做错了什么?
【发布时间】:2021-04-15 12:38:27
【问题描述】:

我正在制作一个包含大量代码的项目,这是我无法将其全部发布的原因之一。 我创建了几个类,其中一些是彼此的朋友。现在,该项目的一个选项是能够创建多种类型的地形,然后将对象插入到“Continente”类的矢量上,它通过下面的循环来实现。

if(linhacomando[1] == "planicie"){
        
        for(int Ploop = 0; Ploop < quantidade; Ploop++){
            
            Planicie P;
            C->AddPlanicie(&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 对象。它应该让它们位于 VPlanicie 向量的 [0][1][2] 处,然后当我要求它向我展示时,它应该打印 Planicie1、Planicie2、Planicie3。

我知道这是一个广泛的问题,可能令人困惑,但我希望得到一些帮助。

【问题讨论】:

  • 某处可能存在未定义的行为。是时候使用调试器了。
  • Planicie P; C-&gt;AddPlanicie(&amp;P); 你存储局部变量的地址。你得到悬空指针和 UB 随之而来。
  • @churill 因为它是一个对象,它无论如何都可以工作吗?因为我正在创建对象并将指向它们引用的指针存储在向量中?
  • @user215272 创建对象,存储指向它的指针,然后销毁对象。现在指针没有指向任何东西。

标签: c++ class object vector


【解决方案1】:
        for(int Ploop = 0; Ploop < quantidade; Ploop++){
        
            Planicie P;
            C->AddPlanicie(&P);
        
        }

所以这个循环的每次迭代都会创建一个Planicie 的实例并将其地址传递给AddPlanicie。然后该对象不再存在。

void Continente::AddPlanicie(Planicie * P){

    VPlanicie.push_back(P);

}

哦,你刚刚添加了一个指向即将停止存在的对象的指针。那个指针就没有用了。

只要你有一个指向对象的原始指针,你就必须能够回答“他指向的对象在哪里”这个问题。在这种情况下,对象不存在,因此一旦循环的下一次迭代执行(或循环终止),指针就不会指向任何内容。

你为什么在这里使用指针?为什么不使用对象本身的向量?如果必须使用指针,请使用管理对象生命周期的指针,例如 std::unique_ptrstd::shared_ptr

【讨论】:

  • 好的,让我看看我是否跟随,我的指针基本上是在一点点指向已被破坏的东西之后,改变它而不是一个一个地制作对象并指向它们,我应该创建一个对象向量,然后如果我需要在以后的迭代中添加更多对象,只需将它们添加到该向量中?
  • @user215272 您不能将对象添加到向量中。一个对象要么在向量中,要么不在。 (数组也是如此。如果 i 是一个不在向量或数组中的值为 3 的整数,如果您“将 i 添加到向量/数组”,那么您实际上要做的就是添加该值3 到向量/数组。)
  • @user215272 但是您可以创建一个包含类实例的向量,并且可以在向量中创建新实例。但是你不能从字面上将一个现有对象放入向量中或从向量中取出一个对象——你必须创建一个新对象才能做到这一点。
  • @user215272 如果i 是3,那么你“将i 添加到向量中”,然后将i 设置为4,向量仍将包含值3,因为i 本身是不在向量中。您所做的只是添加一个与i 具有相同值的新对象。如果您需要从字面上将对象放入和取出向量,则向量必须包含某种指向该对象的指针,最好是std::unique_ptr&lt;&gt;
  • 例如,如果我做vector MyVector。我可以存储指向类型测试对象的指针,但是,如果我通过执行 Test test1 在某个函数上创建测试对象,依此类推,一旦我离开该函数,对象就会被破坏,因此 MyVector 指针什么都没有,对吗?
猜你喜欢
  • 2018-11-25
  • 2013-08-06
  • 1970-01-01
  • 2016-07-18
  • 1970-01-01
  • 2019-12-23
  • 2014-06-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多