C ++有关vector <parent *>的问题

时间:2015-09-13 20:16:08

标签: c++ pointers vector

我有一个班级:

class Parent {
  public:
    virtual void Update() {}
};

和扩展它的类:

class Child : public Parent {
public:
    virtual void Update() {
        /*code*/
    }
};

我将它们存储在矢量中

vector<Parent*> v;

一个名为&#34; tick&#34;的函数将循环遍历每个并运行其更新功能。

问题是:当我将它们添加到矢量并运行&#34; tick&#34;之后一切正常。但当我运行&#34; tick&#34;在某个其他时间点起作用它不起作用(该函数不会被调用,它会阻止程序)。

我试图尽可能地分解它。 产生错误的代码应如下所示:

class Parent {
  public:
    virtual void Update() {}
};
class Child : public Parent {
public:
    virtual void Update() {
        /*code*/
    }
};
class Main {
public:
    vector<Parent*> v = vector<Parent*>();
    void tick() {
        printf("UPDATE");
        for (Parent* &p : v)
            p->Update();
        printf("STOP\n");
    }
};

class Program {
private:
    Main m = Main();
public:
    static class Program* prog = new Program();
    void addOne() {
        Child child = Child();
        Parent* p = &child;
        m.v.push_back(p);
        /*works when tick(); here*/
    }
    void tick() {
        m.tick();
    }
}

int main(int argc, char* argv[]) {
    Program::prog->addOne();
    /*doesn't work when Program::prog->tick(); here*/
    return 0;
}

不工作意味着它打印UPDATE而不是STOP。

1 个答案:

答案 0 :(得分:1)

您没有显示将Child child = Child(); Parent* p = &child; m.v.push_back(p); 添加到向量中的代码,但您描述的症状提供了令人信服的证据,证明您使用指针指向某些超出范围的本地或临时对象(虽然向量仍然保持指针。

您的程序因使用已删除对象的vtable而挂起。 (Seg故障可能比挂起更容易,但这种解释仍然是最适合症状的。)

编辑:现在您展示了该代码并确认了我的猜测:

    Parent* p = new Child();
    m.v.push_back(p);

使用对象指针向量的方法存在很多陷阱,所以只需纠正这一个错误就不会让你站稳脚跟。但是这个错误很容易纠正:

    Child& child = *( new Child());
    Parent* p = &child;
    m.v.push_back(p);

或者根据您可能想要避免更改您尚未向我们展示的代码的其他内容,针对相同运行时行为的更丑陋(但可能更兼容)的源代码是:

new

无论哪种方式,关键是您创建的对象delete在您明确{{1}}之前不会消失,而不是创建一个本地对象,它会立即消失名称超出范围。

如果您无法添加代码以最终删除对象,则设计的一个缺陷(以及早期评论告诉您使用智能指针的原因)是内存泄漏。在一个结构中,如你所示,在main()的生命周期中,实际的内存泄漏无法清除它没有任何后果,可以安全地忽略。但编码和忽略这些泄漏是一个坏习惯,如果你尝试更有趣的项目,会让你陷入困境。