回复: 请教各位大大关于动态内存管理的问题…… 花括号的第一个作用是表达作用,即使会依赖于程序员之间的约定,但是这仍然能够用来表达一些信息,这是为了以后的理解和维护而着想的。以后的需求会变,但是在改动代码之前,至少应该知道这段代码以前的设计情况。
你那段代码的确可以把running泄漏到外面去,但是如果是一开始写代码的人这么做的,那么只能说这是有意而为之,这是初始设计者所设计的;如果是维护者的修改,那么至少代码本身能够表达这样的信息:维护者把一个在最初设计中的局部变量泄露到了最初设计的作用域之外。而如果代码没有那么写,那么维护者根据什么来了解最初的设计?如果没有了解到最初的设计,那么如何判断修改的风险?
这就像reinterpret_cast,虽然编译器不能阻止程序员做危险的转换,但是能够通过“丑陋”的语法来提示程序员其中的风险。把running放进一个更精确的作用域里声明,虽然无法真正阻止一些事情(如果程序员有意乱搞,神仙都没办法),但是作为初始设计者,至少把初始的设计信息都放进了代码。很多机制都是防君子不防小人的。
另外,好像我不记得这个话题跟gc有啥关系,当时只是针对“对代码进行自动化静态分析”这个话题说的,我要表达的就是很多信息(如果程序员不表达出来的话)是无法分析出来的。
内存,未必可以延后释放。延后释放的问题我之前的帖子里谈了。
如果要让gc通过猜测来把数据放到栈上,那相当于程序员写程序时先把这些信息丢弃,然后再让gc来猜测。还不如像C/C++这样直接让程序员来放置。
rvo貌似现在的C++也有,但是却是有副作用的。
重复使用已分配的内存,这是典型的内存池。
所以这些似乎都不能构成支持gc机制的理由。
而Elminster把对象生命期与内存生命期分离开的想法正好与我相反。如果把这两者分开仅仅是产生一个手动版本的析构函数,那么就失去了析构函数最大的优点:在生命期结束时自动调用。
我之所以要把其他资源绑定到内存上,是因为无论是内存还是对象,都需要有生命期管理,而这其实恰恰是现在管理的最大麻烦之一。只要做好了生命期管理,那么把内存交换给系统/内存池这种事情是不会构成多大的麻烦的,而其他资源的释放一般也只是close()之类的操作。
主要的问题是,应该在何时交换内存、close各种资源。只要有一个机制能够确保:在生命期结束时就及时调用指定的行为,那么内存和各种资源的管理都不会太麻烦。析构函数仅仅是在生命期结束时被调用的那个行为。
生命期的管理,我认为是一个普遍的问题,也应该存在通用的解决方案。所以实现了一个良好的生命期管理机制之后,那么所有的资源管理问题都能够从中获得好处。
栈可以看成一种内存管理机制,但是也可以看成一种生命期模型:它是一种嵌套的、FILO的生命期模型。从这个角度看,对于栈来说,内存管理和对象管理是一样的。
至于那些优化,如果会损及语义,那么很可能是不合算的。 |