您的位置:首页 > 其它

游戏引擎的启动与终止【笔记】

2018-03-14 18:26 225 查看
1.游戏引擎 包含 许多子系统,之间可能存在 相互依赖 
2.子系统一般设计为单例类【称为管理器,管理子系统启动,运行,终止】。
3.C++原生的初始化次序:

(首先).编译器完成 全局和静态对象 的内存分配并初始化(在可执行映像内)
(然后).运行时 调用堆栈 内的 局部变量 的内存分配及初始化(在程序堆栈/又称调用堆栈内) 
(最后).运行时的动态分配,即new出来的数据(在堆内存中)
    →(方法1)原生的C++初始化次序不可用,因为单例作为全局或静态对象,总是在调用入口函数main之前初始化,因而无法手动控制他们初始化的次序,这样就没办法处理1所述的子系统间相互依赖。析构也是同理,你看不到他的析构过程,也没法控制他的次序。
4.标记①:
    调用堆栈内的对象总是在 函数被调用的时候才创建 ,那么在函数内我们就可以控制对象的构造及初始化顺序。但是函数内的对象在函数退出时就 可以看做 被析构了(实际上是移动了调用堆栈的内存指针,如果在一个函数退出后,调用下一个新函数以前,仍然可以使用指针访问到这段内存的数据。在新函数调用时,会从内存指针开始进行内存覆盖,这样以后,旧的数据才会丢失)。
    如何把函数内的对象持久化呢?答案是使用static,将它变成函数内静态变量。这种变量不再是存储在调用堆栈内,而是在可执行映像内就被分配好了内存,存储在其数据段或BSS段。虽然存储位置变了,但他初始化的时机却还是函数被调用时。

    不过这样仍然存在问题,虽然数据保存下来了,但是函数退出后,这个数据的访问入口丢了,因为他只在该函数内可见。不过仔细想想,这个问题其实已经解决了,答案在于上文所述的 单例 。只需要函数外再建一个该单例的对象,访问入口就出现了。

    →(方法2)按需构建。此法存在问题,即析构不可控。【且开销很大】

5.简便可行的办法:
    功能拆分,不把子系统的启动功能放在其构造函数里面。即构造析构不做操作,另写 启动和终止函数。

     →(方法3)蛮力法,优点明显,推荐使用。

6.构建专门的管理类,在管理类的内部保存子系统映射,并通过Coding管理类的构造函数,达到所需的子系统构造和启动次序。这相当于在程序外打了个包,管理类模拟了进程的执行,把子系统对象封包到类内部,从而可以直接控制他们的初始化次序。
    →(方法4)OGRE的做法。缺点在于违反了 开闭原则 ,当你需要新的子系统时,你非得回来修改管理类的代码不可。而且一旦这个系统不开源,即你没办法获取管理类的具体代码,对他的修改就束手无策了。严重
4000
影响可扩展性。【幸好它是开源的】

    →神海1的做法类似方法4,但是更多的使用静态分配的单例对象,而非new出来的。new操作很慢,十分影响效能。而且另外,动态分配的内存分布散乱,地址跨度大,比起静态分配的连续内存块,效率也会低很多,而且其减益很可能大于优质算法带来的效能增益
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: