我有一个班级:
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。
答案 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()的生命周期中,实际的内存泄漏无法清除它没有任何后果,可以安全地忽略。但编码和忽略这些泄漏是一个坏习惯,如果你尝试更有趣的项目,会让你陷入困境。