第一次发贴,问各位大牛一个关于效率的问题。
都说C++的效率(运行时)比Java、.Net(C#)要高。这种效率主要来自于什么地方(或者说其他一些语言做了写什么事情损失了效率)。比如由于库的封装,调用的函数更高层会损失效率,不停的安全检查也会,还有其他一些什么原因,谢谢指教:)
--
彪悍的人生,不需要解释。
bool ContactMe(person you)
{
if(you.GoTo("14#344, Tsinghua") && you.Find("范怀宇"))return true;
if(you.MailTo(" dugu...@gmail.com ") || you.MailTo (" fan...@mails.tsinghua.edu.cn "))return true;
if(you.PhoneTo("13488810330") || you.PhoneTo("01062778689"))return true;
if(you.QQTo("120628812") || you.MSNTo(" dugu...@hotmail.com"))return true;
if(you.NetTo(" www.cnblogs.com/duguguiyu "))return true;
if(you.DareToKiss("FuRongJJ"))
{
cout<<"I 服了 U"<<endl;
return true;
}
if(you.GiveMeTwoTicketsFor("MayDay"))
{
cout<<"I love you!"<<endl;
return true;
}
return false;
}
光写一点点简单的测试代码, Java 的性能不比 C++ 差, 但是实际的项目中复杂
了, java 的一些特点才会引起一些性能问题.
runtime range check 这些就不说了, 因为他们带来很多的好处.
Only OO:
Java 没有GP, 编程极度推崇 OO, 大量使用 interface, 这会造成低效, 一个函数
调用, 不仅仅是一个 call/ret语句的问题, 还有参数压栈, 寄存器压栈弹栈等开
销, 同时丢失了表达式重组优化甚至消除机会 (对 C++ 还有临时变量消除机会)
等等不良影响. 同时, 非常 OO & interface 话的代码, 会有一大堆很小的函数,
部分小函数还会有不止一个参数, 对于这种小函数, 参数压栈的代码可能比实际计
算的代码都大(例如 interface 里面的getter, setter), 造成程序 working set
上升, 这对性能也很不利.
这种影响, 在非内层循环, 造成程序 working set 上升对性能的影响可能还比执
行多了几条语句带来的影响大(现在的x86, 空等一个内存字节的到来, CPU 都够时
间执行几十甚至上百条语句了, 我用 TSC 计数器对我的程序进行纳秒级分析优化
的时候, 明显看到等待内存的影响) ; 在循环内层则是直接影响性能.
Java generic 是通过 OO 的类型消除实现的, 和 C++ GP 只有表面相似, 不是一
个东西.
C++ 的 STL 用于 native type 的时候, 效率是非常高的, Java 的容器还要
boxing, unboxing, 损失也很大.
GC:
现代的GC 能够带来比人工分配释放内存更少的总体内存管理消耗时间, 但是 Java
的 GC, 似乎却常常使用大量的内存, 先不管挤占了别的程序或者 OS cache,
buffer 的性能优化机会, 光是使用大量的内存, 造成的大 working set 就会导致
CPU 的 cache 工作不优化, 最终的结果有可能是总体内存管理消耗的时间少了,
但是程序运行却慢了.
C++ 里面几个优秀的 mallloc 库, 不但考虑到尽量重用最近释放的内存块(它们多
半在cache 中还有entry), SMP 环境中, 还能考虑 CPU 亲和性, 这对 CPU 的
cache 有很大的帮助,
其他, 例如 serilazation:
Java 不能直接操作内存, 将对象送到网络, 文件, 数据库, 或者从其中取出, 都
要用到 serialzation, Java 的 serialzation 似乎从一开头就很慢, 是一个性能
杀手, 而这个杀手的身影又常常出现.
Java 我懂得不多, 其他我就不怎么知道了.
怀宇范 写道:
--
反者道之动,弱者道之用
对于gc,我感觉性能的问题倒不算很大,boost的那几个智能指针性能都不怎么样。问题是现在的一些gc,Java的也好、C#的也好,都是不确定的。冷不定地出来鼓捣几下,把别人的时间都给占了。结果,即便你gc性能比手工的好,时不时地让系统停个一秒半秒的,也足够让用户骂娘了。
还有就是,C#吹嘘分配内存有多快,比C++的都快。可就是不说它回收内存和压缩内存有多慢。而且在你,最不希望慢的时候慢。
智能指针, 那玩意就是图个方便, 效率? 就别提了.
On 10月9日, 下午12时51分, pongba <pon...@gmail.com> wrote:
> On 10/9/07, Huafeng Mo <longshank...@gmail.com> wrote:
>
>
>
> > 对于gc,我感觉性能的问题倒不算很大,boost的那几个智能指针性能都不怎么样。问题是现在的一些gc,Java的也好、C#的也好,都是不确定的。冷不定 地出来鼓捣几下,把别人的时间都给占了。结果,即便你gc性能比手工的好,时不时地让系统停个一秒半秒的,也足够让用户骂娘了。
我说的比较好的库, 并不是指 boost 里面的智能指针.
智能指针, 那玩意就是图个方便, 效率? 就别提了.
On 10月9日, 下午12时51分, pongba <pon...@gmail.com > wrote:
> On 10/9/07, Huafeng Mo <longshank...@gmail.com> wrote:
>
>
>
> > 对于gc,我感觉性能的问题倒不算很大,boost的那几个智能指针性能都不怎么样。问题是现在的一些gc,Java的也好、C#的也好,都是不确定的。冷不定 地出来鼓捣几下,把别人的时间都给占了。结果,即便你gc性能比手工的好,时不时地让系统停个一秒半秒的,也足够让用户骂娘了。
> > 还有就是,C#吹嘘分配内存有多快,比C++的都快。可就是不说它回收内存和压缩内存有多慢。而且在你,最不希望慢的时候慢。
>
> 这个... 有数据吗?现在最牛逼的分代垃圾收集就是平摊时间复杂度的想法啊..
>
> --
> 刘未鹏(pongba)|C++的罗浮宫http://blog.csdn.net/pongba
> TopLanguagehttp://groups.google.com/group/pongba
--
反者道之动,弱者道之用
在07-10-9,redsea <red...@gmail.com> 写道:我 说的比较好的库, 并不是指 boost 里面的智能指针.智 能指针, 那玩意就是图个方便, 效率? 就别提了.
On 10月9日, 下午12时11分, pongba <pon...@gmail.com> wrote:
> 其实你都说了啊:间接层,语言模型的抽象层次、JIT的开销、GC、range check、other runtime checks...
> 也就不外乎这些原因了。
>
> 另外,C++标准网站上有一个Performance TR,可以看看。
>
> 其实我觉得以上这些性能因素会随着并发的普及逐渐变得不那么重要。
>
> 有谁做过大型统计的?或者看过有大型统计数据支持的文章的?出来吱一声啊 :P
>
> On 10/9/07, 怀宇范 <dugugu...@gmail.com> wrote:
>
>
>
>
>
>
>
> > 第一次发贴,问各位大牛一个关于效率的问题。
>
> > 都说C++的效率(运行时)比Java、.Net(C#)要高。这种效率主要来自于什么地方(或者说其他一些语言做了写什么事情损失了效率)。比如由于库的封装 ,调用的函数更高层会损失效率,不停的安全检查也会,还有其他一些什么原因,谢谢指教:)
>
> > --
> > 彪悍的人生,不需要解释。
>
> > bool ContactMe(person you)
> > {
> > if(you.GoTo("14#344, Tsinghua") && you.Find("范怀宇"))return true;
> > if(you.MailTo(" dugugu...@gmail.com ") || you.MailTo (" fanh...@mails.tsinghua.edu.cn
> > "))return true;
> > if(you.PhoneTo("13488810330") || you.PhoneTo("01062778689"))return
> > true;
> > if(you.QQTo("120628812") || you.MSNTo(" dugugu...@hotmail.com"))return
> > true;
> > if(you.NetTo("www.cnblogs.com/duguguiyu"))return true;
>
> > if(you.DareToKiss("FuRongJJ"))
> > {
> > cout<<"I 服了 U"<<endl;
> > return true;
> > }
> > if(you.GiveMeTwoTicketsFor("MayDay"))
> > {
> > cout<<"I love you!"<<endl;
> > return true;
> > }
>
> > return false;
> > }
>
> --
> 刘未鹏(pongba)|C++的罗浮宫http://blog.csdn.net/pongba
> TopLanguagehttp://groups.google.com/group/pongba- 隐藏被引用文字 -
>
> - 显示引用的文字 -
Huafeng Mo 写道:
TopLanguage
http://groups.google.com/group/pongba
你说的是正道, 但是我已经是破罐破摔了:
反正用 struct 也要手工逐个调用构造函数, 不是好的解决方案, 干脆我就用
mixin 了, 这样就省掉为了 struct 中需要 public 出来的函数写 wrapper 代码
转接调用.
JIT损失会很大吗?
恩。有没有具体的一些比较数据啊,有时候看到一些数据和评论,动不动说性能上差上几十倍,头皮发麻。我个人的感觉倒还好,没遇到那么恐怖的性能瓶
颈。。。
On 10月9日, 下午12时11分, pongba <pon...@gmail.com> wrote:
> 其实你都说了啊:间接层,语言模型的抽象层次、JIT的开销、GC、range check、other runtime checks...
> 也就不外乎这些原因了。
>
> 另外,C++标准网站上有一个Performance TR,可以看看。
>
> 其实我觉得以上这些性能因素会随着并发的普及逐渐变得不那么重要。
>
> 有谁做过大型统计的?或者看过有大型统计数据支持的文章的?出来吱一声啊 :P
>
> On 10/9/07, 怀宇范 < dugugu...@gmail.com> wrote:
>
>
>
>
>
>
>
> > 第一次发贴,问各位大牛一个关于效率的问题。
>
> > 都说C++的效率(运行时)比Java、.Net(C#)要高。这种效率主要来自于什么地方(或者说其他一些语言做了写什么事情损失了效率)。比如由于库的封装 ,调用的函数更高层会损失效率,不停的安全检查也会,还有其他一些什么原因,谢谢指教:)
>
> > --
> > 彪悍的人生,不需要解释。
>
> > bool ContactMe(person you)
> > {
> > if(you.GoTo("14#344, Tsinghua") && you.Find("范怀宇"))return true;
> > if(you.MailTo(" dugugu...@gmail.com ") || you.MailTo (" fanh...@mails.tsinghua.edu.cn
> > "))return true;
> > if(you.PhoneTo("13488810330") || you.PhoneTo("01062778689"))return
> > true;
> > if(you.QQTo("120628812") || you.MSNTo(" dugugu...@hotmail.com"))return
> > true;
> > if(you.NetTo("www.cnblogs.com/duguguiyu"))return true;
>
> > if(you.DareToKiss ("FuRongJJ"))
> > {
> > cout<<"I 服了 U"<<endl;
> > return true;
> > }
> > if(you.GiveMeTwoTicketsFor("MayDay"))
> > {
> > cout<<"I love you!"<<endl;
> > return true;
> > }
>
> > return false;
> > }
>
> --
> 刘未鹏(pongba)|C++的罗浮宫 http://blog.csdn.net/pongba
Java, .Net, 限于需要快速完成编译, 优化级别不可能太高; 即使它们的编译器选
择生成中间码的时候做深入优化, 删除很多中间码, 最终不过接近上述系统的优化
编译而已; 根本不算啥; 只是可以在 windows 这种 close 系统上面抖抖威风而已.
不过, 我以前做过一个编译器, 根据我的知识, 编译器的优化就是在中间码(&带上
符号表)上进行的啊, C/C++ 的编译器中间码, 优化之前, 并不会损失程序员的意
图, 难道 Java 的有所不同 ?
Huafeng Mo 写道:
> 关于jit,现在似乎有了一些新的论调。java等语言通过中间码发布程序,最初
> 是在vm上解释执行,效率自然大打折扣。而使用jit,在代码第一次被调用时编
> 译成本机代码,效率大幅提高。是否可以jit的编译也可以省去呢?那就在安装
> 时编译吧。
> 这样,便产生了一个推论。既然在安装时或调用时编译,那么此时已经知道系统
> 特别是cpu的类型。于是,便可以面向特定的系统平台优化编译。得到的代码甚
不过, 我以前做过一个编译器, 根据我的知识, 编译器的优化就是在中间码(&带上
符号表)上进行的啊, C/C++ 的编译器中间码, 优化之前, 并不会损失程序员的意
图, 难道 Java 的有所不同 ?
Huafeng Mo 写道:
> 关于jit,现在似乎有了一些新的论调。java等语言通过中间码发布程序,最初
> 是在vm上解释执行,效率自然大打折扣。而使用jit,在代码第一次被调用时编
> 译成本机代码,效率大幅提高。是否可以jit的编译也可以省去呢?那就在安装
> 时编译吧。
> 这样,便产生了一个推论。既然在安装时或调用时编译,那么此时已经知道系统
> 特别是cpu的类型。于是,便可以面向特定的系统平台优化编译。得到的代码甚
> 至比直接编译成本机代码的还要好。
> 这个思想逻辑上没有错,或许也是未来的发展方向。sutter在exceptional c++
> style中,分析了在编码、编译、链接、安装、运行等时候,inline的可能性。
> 同样的思路,也可以推广到性能优化上。
> 但是,就目前的技术水平而言,我觉得要让一个jit编译器能够达到一个真正编
> 译器的优化能力,还很困难。而且中间码不是源代码,留给编译器发挥的空间小
> 得多。源码能更多地体现程序员的意图,而中间码则失去了很多对优化有用的信
> 息。而且受制于中间码的设计局限,也不可能面向所有平台系统都能达到很好的
> 效果。
> 但是,不管怎么说,Java、.net的性能问题不会仅仅由单独的哪一个问题引发,
> 而是众多缺陷和不足引起的。其中,愚蠢的对象模型和内存管理体系是罪魁祸首。
>
现在使用 gentoo, slackware, lfs 等版本的linux, 整个OS 带应用就是自行编译
的, freebsd 的 ports, 软件都是从源代码进行编译, debian, ubuntu 等debian
系的linux 也可以一个命令就可以简单地自行编译软件. 而这些系统的编译, 缺省
就是和系统的 CPU 一致的, 优化级别可以很高.
在07-10-9,red...@gmail.com <red...@gmail.com> 写道:现 在使用 gentoo, slackware, lfs 等版本的linux, 整个OS 带应用就是自行编译
的, freebsd 的 ports, 软件都是从源代码进行编译, debian, ubuntu 等debian
系的linux 也可以一个命令就可以简单地自行编译软件. 而这些系统的编译, 缺省
就是和系统的 CPU 一致的, 优化级别可以很高.
这个应该是未来的发展方向吧。很好的思路,我喜欢。 :)
--
反者道之动,弱者道之用
现实上, C++ 用intel 的工具, 能够进行这些分析优化.
如果runtime 做这个分析,成本太高了, 因为这个粒度太细了.
如果不同分支路径的概率基本不变, 提前分析的方法已经 ok 了, 如果不同分析路
径的概率经常变, runtime 经常分析的成本无法承受; 要找一个合适的应用场合,
还是不容易的.
Atry 写道:
> 理论上说,运行的时候编译可能效率更高,比如说可以统计出不同分支路径的概
> 率, 根据概率调整生成的代码,效率可能更高。
刚刚生成还没有优化的中间码, 再加上符号信息, 就可以有源代码想表达的全部的
信息了, 一般都是在这个的基础上做表达式优化, 常量从循环内抽离之类的优化.
整个程序的中间码都得到后, 会分析哪些代码根本不会调用到, 去掉它. 更先进的
分析, 似乎包括在全局代码都在的情况下, 可以分析出哪个函数的参数都是常量调
用的, 可以去掉这个参数的压栈, 这个值变成函数内部的常量; 某些 virtual 函
数的调用, 可以分析出具体调用的函数; 如果某个函数接受的函数指针在上下文可
以分析出来, 那么函数指针实际可以 inline 掉等等, 这些更高级的东西, 我懂得
不多.
这些高级的优化, 如果在 JIT 的时候做分析, 恐怕分析成本相对高了----- 当然
对于分析一次, 会执行半年的服务器, 也没有什么很大的关系.
Arty 提到的分支优化, 分析成本也相对有点高:
第一步要做代码热点分析, 大粒度分析的话代价不高, 正常数据输入的时候跑跑,
进行中断采样即可.
第二步要进行详细的路径分析, 对于大粒度分析出来的热点区域, 重新编译, 每个
汇编级别的判断语句之后, 加入代码记录执行次数, 对于内层循环, 这样的代价就
比较大了.
但是分支 JIT 分支优化有个好处 ---- 每个JIT程序都能够享受到, C++ 的程序,
如果没有购买 intel 的工具, 就没有办法做这种优化了.
在很多其他领域可能很有进展, 只关注 Windows desktop 平台可能看不到这些变
化 ---- Windows 用复杂的方法解决复杂的问题, 用更复杂的方法解决它自身方法
带来的问题, 东西越来越庞大, 迟早跑不动.
现在的一些进步, 例如, multicore 跑到什么程度了 ? 已经有公司提供 64core
的pcie卡产品给video/networking 用了, 很快 128core 的产品就出来. 64core
的性能是 Intel Xeon 2core 的10倍, 价格只要 $435.
这么一个平台, 编程技术不发展, 根本就无法利用. 这个平台还很有趣, 所有的
core 的 L2 cache 综合起来, 作为所有 core 的 L3 cache ---- 既然这个cpu 是
设计来做 cpu bound 的处理, 大家干的活可能差得不多, 我的 cache 里面没有,
你的cache 里面就可能有了.
> 再问一个,源码编译成中间码时,是否还可以做一些优化?有没有可能发生弄巧
> 成拙的情况?
>
静态语言的优化, 一般是每个模块编译成中间码后优化一次, 整个程序各个模块都
编译完了, 整体信息齐备之后再优化一次. C++ 的模板也有一些相关的优化, 不过
我不懂.
优化当然可能会有弄巧成拙的可能, 例如, 你 google 一下 pointer alias, 可以
知道这个东西的影响, 但是gcc 有选项可以让它认为不用考虑这个问题. --> 你可
以告诉 gcc, 所有指针都没有别名, 真没有的话, 你的程序就跑得更快了, 而万一
有的话, 你的乐子就大了 ---- 可能搞来搞去就搞不出可以重复bug 的输入数据.
用危险优化的后果, 问问激进的gentoo 用户就可以知道不少: 一些激进的用户,
不管软件推荐的级别, 自己尝试更危险的优化, 会不时碰到编译结果有问题, 有些
问题可能是跑很长时间偶尔出现的.
对 gcc 而言, -o2 的优化一般还是安全的, -o3 包含的优化可能就有危险了.
c/c++ 发展的同时, 优化技术同时发展, 因此, 这个语言的设计本身没有考虑到很
多配合优化, 有一些可以带来收益的优化无法准确分析而无法使用, 或者 at your
own risk.
现在设计的D 语言, walter 本身是C++ 编译器老人了, 他知道这些问题, 所以他
设计的语言特性, 同时会考虑对用户的有用程度, 危险性, 以及对编译器的编译速
度, 优化的影响. const 语法语义的设置现在还没有定稿, 也是因为考虑太多
---- C++ 的const, 当年可能没有怎么考虑清楚就出来了, 变成了一个表面看起来
很有用, 实际上多数情况也是很有用, 但是在某些情况下, 却会误导程序员, 我还
不知道它会不会误导编译器, 不过编译器多半可能不甩它.
C语言的硬件亲和性保证其可以很好的适应这个新架构.(原来在NP上开发用的就是MicroC(一种C方言)).
GPGPU也是最先支持了C语言和Lua语言.
目前,GPU的晶体管数目已经大大超过CPU.
所以,这种趋势应该会越来越明显吧.
On Oct 9, 11:49 am, "怀宇范" <dugugu...@gmail.com> wrote:
> 第一次发贴,问各位大牛一个关于效率的问题。
> 都说C++的效率(运行时)比Java、.Net(C#)要高。这种效率主要来自于什么地方(或者说其他一些语言做了写什么事情损失了效率)。比如由于库的封装 ,调用的函数更高层会损失效率,不停的安全检查也会,还有其他一些什么原因,谢谢指教:)
>
> --
> 彪悍的人生,不需要解释。
>
> bool ContactMe(person you)
> {
> if(you.GoTo("14#344, Tsinghua") && you.Find("范怀宇"))return true;
> if(you.MailTo(" dugugu...@gmail.com ") || you.MailTo("
> fanh...@mails.tsinghua.edu.cn "))return true;
> if(you.PhoneTo("13488810330") || you.PhoneTo("01062778689"))return true;
> if(you.QQTo("120628812") || you.MSNTo("dugugu...@hotmail.com"))return
> true;
> if(you.NetTo("www.cnblogs.com/duguguiyu"))return true;
>
> if(you.DareToKiss("FuRongJJ"))
> {
> cout<<"I 服了 U"<<endl;
> return true;
> }
> if(you.GiveMeTwoTicketsFor("MayDay"))
> {
> cout<<"I love you!"<<endl;
> return true;
> }
>
> return false;
>
>
>
> }- Hide quoted text -
>
> - Show quoted text -
请教楼主:
VC8可以支持托管和本地代码共存,那是不是可以将难以掌控生存期的对象用托管(gcnew),而容易掌控的则用纯C++的内存设施.
不知一个程序中加
入了托管后,其本地代码部队会不会受效率的影响.
longsh...@gmail.com
http://blog.csdn.net/longshanks/
另一个,C#有个Disposable的interface,实现了这个的class可以调用Dispose()做手工回收。
最后,这种循环内部的,用Pool不行么?
On Oct 9, 1:38 pm, "Huafeng Mo" <longshank...@gmail.com> wrote:
> 数据没有。一直用C++,倒也不太操心这种事。
> 只不过有那么几次体会。都是在.net下调试程序,
> 调一些循环,循环里有不少内存分配(.net里什么内存都得分配)。几次循环以后(大概10多次吧,具体记不清了),ide总要停顿那么一下,有点像死锁。大约不到半秒左右,又开始运行了。后来几个C#er告诉我,可能是在gc。由于在调试,系统不忙,gc就来劲了,很积极地回收。但让我惊讶的是系统停顿的时间,就这么点内存gc,非但感觉明显,而且是很明显。我说,这种效率要是关键时刻还不死人哪。他们告诉我,如果不想要他在最关键的时候打搅你,事先手工gc一下。这倒也不错。不过后一句话让人丧气:只是手工gc不一定会做。:(
> 然后,我查了msdn,里面说,.net的内存分配快,因为内存压缩过,只需移动内存池指针。这就明了,内存压缩比单回收内存可费时多了,外加我频繁分配内存,短期对象之类的鸡零狗碎多,内存压缩比较频繁。
> 尽管.net的内存池分三代,可遇到频繁的短期对象,挡也挡不住。更何况.net没有栈对象,所有对象,再小也得在堆里,鸡零狗碎的更多。
> 另一个角度讲,Java和.net的gc不是gc本身慢,而是把原本不应该gc的东西也gc了,这样神仙也没办法。
> 想来想去,还是RAII好啊。:)
>
> 在07-10-9,pongba <pon...@gmail.com> 写道:
>
>
>
>
>
> > On 10/9/07, Huafeng Mo <longshank...@gmail.com> wrote:
>
> > > 对于gc,我感觉性能的问题倒不算很大,boost的那几个智能指针性能都不怎么样。问题是现在的一些gc,Java的也好、C#的也好,都是不确定的。冷不定地出来鼓捣几下,把别人的时间都给占了。结果,即便你gc性能比手工的好,时不时地让系统停个一秒半秒的,也足够让用户骂娘了。
> > > 还有就是,C#吹嘘分配内存有多快,比C++的都快。可就是不说它回收内存和压缩内存有多慢。而且在你,最不希望慢的时候慢。
>
> > 这个... 有数据吗?现在最牛逼的分代垃圾收集就是平摊时间复杂度的想法啊..
>
> > --
> > 刘未鹏(pongba)|C++的罗浮宫
> >http://blog.csdn.net/pongba
> 另一个不容易看到的地方就是,C++中在一个类中声明的成员对象(不是指针或
对于你这种情况,不知道类似于StringBuilder的类有没有帮助。
On Nov 12, 11:27 am, "莫华枫" <longshank...@gmail.com> wrote:
> C#的struct类似于C++的pod,缺少构造和析构功能。同时,一个更大的问题使得struct无法被广泛使用:对于struct(值类型),=操作符表示值拷贝,而对于class(引用类型),=操作表示引用的赋值。两者具有完全不同的语义。如果我在项目中定义了一个struct
> A,开发到一半后,发现A需要增加一些struct无法涵盖的功能,必须改成class。由于=对于两者的语义不同,那么存在=操作的代码都将可能成为bug,相关代码必须修改。所以,为获得开发中的自由度,一般很少使用struct定义稍具复杂性的类型。
> 而C++或C++/CLI从语义上无需区分值类型和引用类型,两者行为相同,不存在这些问题。所以,从这一点上讲,C++这种传统的内存模型更加灵活可靠。C++/CLI尽
> 管为了适应.net平台,被迫将栈语义变成一种语法糖,但其带来的好处,是C#所无法比拟的。
> Disposable是完全为了.net对象模型而生的,
> 它导致了一个对象的内存清理必须手工实现。而C++的自动对象(栈对象、子对象)可以保证自动调用析构释放资源,这就是raii。相比C#的手工dispose、using和java的finalization,简洁优雅得多。(Sutter的blog上有一篇文章专门比较了他们的差异)。gc自动化了内存管理,但对于其他资源缺乏自动化的手段,这是C#和java思维的古怪之处:不相信程序员能够很好地手动管理内存,却认定他们能够手动地管好其他资源。
> 对于循环内部,基本上都是new出来的东西(非确定性内存分配),插入容器,pool起不了什么作用。对于gc而言,这些时必须承受的负担。但是,除此以外,
> 在.net上(
> 不仅仅是C#),所有引用类型(我们还敢用值类型吗?)都在栈中分配,由gc回收。编程中,多数的对象都可以有确定的生存期,比如局部对象、一个对象的子对象等等。这些对象通常都是些诸如string之类的小型对象。他们本该用完就释放,也能做到这一点。
> 但鉴于.net的对象模型,这些鸡零狗碎都被迫由gc统一收集,gc的负担能不大吗?
> 另一个不容易看到的地方就是,C++中在一个类中声明的成员对象(不是指针或引用)通常都在宿主对象的内部构成子对象,宿主对象释放,子对象也释放。
> 而.net中一切都是引用(我们不敢用值类型对吧),宿主对象和子对象是独立的,gc必须分两次加以回收,gc的负担又增加一块。
> 总之,gc的名声都是.net之类的蹩脚对象模型搞臭的。
>
> 在07-11-12,Googol Lee <googol...@gmail.com> 写道:
> longshank...@gmail.comhttp://blog.csdn.net/longshanks/
多谢多谢,关于struct和class在赋值上的语义区别倒还真没想过。