查看单个帖子
  #96 (permalink)  
旧 2008-03-08
sjinny 的头像
sjinny sjinny 当前离线
普通会员
 
注册日期: 2008-02-01
帖子: 66
sjinny 正向着好的方向发展
默认 回复: 请教各位大大关于动态内存管理的问题……

我前面那个例子就是:
代码:
for( bool running= true; running; ){ switch(){ ... } }
还有,我那个针对的是代码的表达能力,针对的是代码的静态分析……这些都是为人服务的……
编译器不用猜测人的意图,但是人自己需要知道……编译器不需要知道在初始设计之中那个running的含义和使用范围,更不需要知道以后修改时需要维持哪些约束、哪些约束是可以放弃的。但是人需要知道,所以在代码里表达出来会更好。

我不认为构造和析构函数把内存管理和其它管理混为一谈。构造函数和析构函数仅仅是提供了一种手段,这种手段让你能够把你所期望的行为绑定到某个内存块的生命期边界上:生命期开始时调用构造函数,结束时调用析构函数。构造函数和析构函数并不是专门用来管理资源的,它的使用效果取决于你的选择。就好象多线程中给mutex加锁的操作。一个Guard对象并不是管理mutex的,而仅仅是为了提高加锁/解锁的自动化程度以减少出错的机会。构造函数和析构函数仅仅是把行为绑定到内存块生命期边界上的手段。
至于你所说的在传递T时会有无法预知的行为的问题,这不是构造函数或析构函数的问题,这是抽象引起的问题。当然其中还有值语义的因素,但是这本身也可以看作一种抽象。如果很多种不同的对象被使用时必须要有各自的初始化行为,那么当这行为被放进构造函数时,它们可以用相同的形式来传递;如果没有放进构造函数,那么这些无法省略的初始化行为就不得不在函数内显式调用,那么问题就在于:
1.不同类的初始化接口可能不相同;
2.函数编写者可能会忘记调用初始化接口。
3.当进行GP时,你如何知道这个T是否应该调用初始化接口呢?
构造函数提高了GP的抽象能力。
我不记得模板能不能限制或识别模板参数是否为指针了,似乎用TypeTraits可以做到。但是,即使无法做这种区分或限制,那么:
传入的T是什么,取决于这个模板的使用者。如果使用者需要使用引用语义的传递,那么可以选择把指针类型传给模板,或者做个wrapper。
就好象一个电磨,可以绞肉,也可以打果汁,电磨只知道把放进去的东西搅碎,至于其语义,那是使用者的事情。如果一个模板需要对外界有很多的了解,那么意味着在模板面前的世界的抽象度相对比较低,那还不如用普通的函数和类。

值语义有时会有缺陷,但是它有自己存在的意义和必要性。新标准引入的move语义也并不是值语义的替代。我个人的体会是,值语义比引用语义更容易使用,因为它把一次模块交互的两端(即传递值的源模块和目的模块)分开了,交互的两个模块间没有物理性的关联,传入的值再怎么变动也不会影响到源模块。如果传递的是指针,那么模块间的耦合度就变高了,毕竟目的模块无法得知源模块是否会继续使用这个对象,那么要么就让模块间的了解变多(增加耦合),要么就是增加风险(目的模块对传入的对象的误用可能会引起源模块的错误,甚至正常使用也不是100%安全的)。所以我现在都是尽量使用值语义,即使我知道会有更多的复制,但是在我profile之前我没有任何根据来优化,而profile之后也可以用内存池或其他的手段来优化。

不同的东西的生命期管理有不同的特点。
这点我自然会承认,但是这点并不能证明“不同的东西的生命期管理没有共性”吧?而我要把其他资源的管理绑定到内存上,就是为了使用内存管理中现成的生命期管理功能,更具体的说,借用的无非就是生命期边界的管理功能。这个边界就是生命期的开始和结束。我假设任何资源的生命期都只会有一次开始和一次结束。如果不符合这个假设,那么我觉得完全可以把那种生命期分解为这种结构。比如,如果要复用对象,那么只需要把对象的一次使用看作一个完整的生命期;比如mutex加锁,mutex存在的过程中会有多次加锁/解锁,但是却可以分解为多次Guard的构造和析构。这种“一次生命期中只有一次开始和一次结束”的模型虽然不能表达所有的情况,但是是一种有效的工具。而这种模型就是我所认为的各种资源的生命期管理的共同点。

至于内存管理和FILO的问题。我那段话说明的只是栈的特点,如果某些栈在编译器优化之前不遵循FILO的约定,那么请告诉我……
其实我那段话只是把栈拿来作个例子,用以说明从生命期的角度来看到的栈。重点是把栈作为生命期模型的实现,至于FILO则是次要的。

关于优化,我认为作为语言和工具,要提供的只是优化的手段和保守的自动化优化。优化的根本还是在于profile和程序员的分析。rvo貌似是不得已而为之的,move语义的出现应该会成为rvo的替代,或者说能够使rvo时函数的语义与语法一致。
而你说的这句:“一个损及优化能力的语言语义模型是失败的”,我的理解是你在说C++的语义模型是损及优化能力的,那么能不能具体的说说C++的什么语义损及了优化能力呢?又有什么语言能够在对应的方面有着不损及优化能力的语义呢?毕竟我没有在这句话中看到“如果”二字。

如果因为一个rvo就能把整个语言否定掉,那我也无话可说了。反正世界上不会有完美的语言,那么任何语言都能因为局部的问题而否定掉全局。

最后那句“把内存管理和副作用混为一谈”中的“副作用”是指什么?我不明白如果一个效果被人认为是副作用,那么这人还会有意地去把内存管理和这种副作用混合起来吗?


PS.感觉我经常照着别人的帖子一段一段的回复,而我得到的经常只是无穷的反问,甚至发问者似乎没有仔细看我的文字。这样很累。
回复时引用此帖