C++ criticized/defensed (cont'd)

ajoo 2002-06-11 11:33:31
reached the 30 posts limit. So we can talk here.
huwx:
compared to gj, template is more like macro. It is just an advanced macro.
generics have nothing to do with single inheritance. no relationship, no contradiction.
What generics is for? type safety. That's it. template has meta-programming, but gj does not. template has code-bloating, gj does not.

copy&paste my question here again for discussion:

give an example of sizeof:
I had a discussion with a C++ guy on mit bbs.
I would say his C++ knowledge is well beyond average level. He knows pretty much about meta-programming.
He raised a question for one problem:

need to implement a template based class, in which we need the following method
void add(T val);

What he's puzzled is that he does not know what the T is and he wanted his code as efficient as possible.

He's concerned about the overhead of copying in pass-by-value,
While, he's not too happy about the extra address indirection of pass-by-ref either.

So, he's got a plot.

Define a size limit, for type T that sizeof(T)>limit, use const T& for the add method.
for other types, use T for the add method.

How do you guys think about his design? Is it scalable? Is it cross-platform? Should he forget about "programming"?

...全文
169 79 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
79 条回复
切换为时间正序
请发表友善的回复…
发表回复
cloudwu 2002-06-14
  • 打赏
  • 举报
回复
http://www.microsoft.com/msdownload/iebuild/ime5_win32/en/ime5_win32.htm

这里可以当到中文支持. btw, 我用的 EWin2K, 98 不知可不可以.


那个宏的诞生是因为我的那个平台上没有 C++, 也不能直接用汇编.
而需要做一些好象模板特例化的工作, 只好用宏来模拟
(N>0)?(a):(b) 这样的代码, C 一般不给你优化的很好的, 即使 N 是常数.
但是 (N>0) && (a) || (N<=0) && (b) 却可以.
因为 C 标准里定义了它的逻辑表达式运算规则.

而且表达式写成一行, 跟多行写优化的效率也不一样.

所以有了那种宏的出现. 当一段代码需要 50 个周期还是 45 个周期
很重要时, 这些宏技巧就可以带来好处了.

而且更多的时候, 我喜欢把宏当玩具玩, 而不是解决实际问题 :)

在很多情况下, 为了效率, 我禁止掉对象的复制. 但是需要对象的传递.
比如有一个Object a, 我希望它可以传递给 Object b.
比如写 Object b=a, 但是 a 不会再被使用.

这在诸如 vector<Object> 的实现中就很有用, 容器体积增长的时候,
现在需要大量的对象复制, 很多情况下, 传递比复制的开销小.
而且有的对象实现 copy 安全很困难, 但是实现传递安全却很容易.

又比如, 我在函数里生成了一个 string, 想把 string 做返回值的时候
也需要复制一份. 但是很多情况, 我需要的只是把 string 传递出去.

现在最多只能使用 cow 来减少数据copy, 但减少不了引用计数变量
本身的增减变化.

在我自己上个项目中, 我用 template 定义出一个传递语义的函数,
来干这种事情, 然后自己实现 vector 这样的容器来管理我的对象,
并把自己的对象的 operator= 这样的操作再禁止掉.

不过这样很不舒服 ;(
ajoo 2002-06-14
  • 打赏
  • 举报
回复
Hey, cloudwu, do you know of any chinese platform that I can download and use on my EWin98?
Highly appreciate it!

no offsense, but I don't like your "_if" macro, although I'm also a macro lover. I would never use macro when I can avoid code duplicating using template or function.

"我对 C++ 比较痛恨的是只有复制的语义,而没有一种反应对象传递的语义"
don't quite understand. could you be more specific?
auto_ptr has its own semantics, it does not seem to be c++'s fault ah!
cloudwu 2002-06-14
  • 打赏
  • 举报
回复
;( 如果大家用中文写多好 (或许不可能的)
欺负我可怜的英文水平, 就认得那么几个单词.

ps. 我爱死宏了. 有时候极端需要速度, 又不能用汇编的时候.
定义出这样的东西
#define _if (
#define _elseif )) || (
#define _else )) ||
#define _endif ))
#define _then && (

把老长的语句写在一行表达式里, 让编译器来优化, 感觉相当不错 :)

我对 C++ 比较痛恨的是只有复制的语义,而没有一种反应对象传递的语义,
导致 auto_ptr 这种的东西放不到stl 的容器里.
只能用COW, 通过引用计数来表达对象的复制. 这在某些情况下,
还是效率所不能接受的.
ajoo 2002-06-14
  • 打赏
  • 举报
回复
prototype:
don't want to argue about the liabilities. the fact is, code written in C++ is not easy to port, that's why I said "C++ is not cross-platform even on source code level".
but code in Java does not have the problem at all.
magic number? whatever you call it. but if he wants to tune the size limit, what else can he use?

cloudwu: don't quite understand your app. But anyway, i don't think compiler would be that smartly stupid. :) (I mean, it's hard to be that stupid)

btw, when you use VC's view assembly code in VC, you are looking at debug version, not quite useful to see the optimizations.
cloudwu 2002-06-14
  • 打赏
  • 举报
回复
为什么编译器会在那些地方优化程度不一样, 我明白, 但是讲不清楚.
如果你多看看代码编译的目标代码, 慢慢也能明白.
VC 做的优化够好了, 但是在这里依然目标代码有差别.
理论上代码是等价的, 但是理论和实际总是有差别.

至于我曾经处理的那个问题, 所以不用指针, 也有它的道理.
因为对象中数据和状态是分开的. 状态信息是 POD 的, 数据是可以共享
一片内存的. 我需要共享那片数据区, 但是有自己的状态值.
对数据区又不需要采用引用计数来管理, 因为共享数据区的对象间
本身有主次之分, 永远是主对象来分配和释放这块数据区.
等重要的是, 程序运行时有大量的构造和析构,new 和 delete 操作,
如果将对象中 POD 的分离出来, 可以加快很多速度.
比如可以专门开一个堆, 重写 new 函数后, 在这个专有的堆上按栈的方式
分配, 而永远不释放. 等到整个一组对象的使命完成, 再一次把整个堆
拿掉. 这样节省了大量的时间.

这是我好几年前做的一个东西, 那个时候对 C++ 的理解远不如现在深刻.
现在再设计可能是另外一个样子.
我想说明的是, 有时候, 牺牲一些严谨和代码重用性, 采取一些比较
糟糕和晦涩的设计, 能够带来很高的效率 :) 当效率非常的重要的时候,
这样做是有价值的.
prototype 2002-06-14
  • 打赏
  • 举报
回复
your word raises a very good point. hmmmm... the guy's code
will still not be portable. but note it originates from its
design -- branching on some agents that is completely out
of control, not the language features.
btw, the '4' in '4*sizeof' is a magic number. :-)
ajoo 2002-06-14
  • 打赏
  • 举报
回复
also, cloudwu, why don't use pointer? no overhead at all.
ajoo 2002-06-14
  • 打赏
  • 举报
回复
prototype:
Oops! misunderstanding. :)
you are sure struct{char c;} will never be smaller than int?

and normally, he wouldn't just use sizeof(int), maybe something like "4*sizeof(int)", do you think so?

cloudwu(云风) :
don't think compiler can be that stupid. "," and ";" won't make any difference in the transformed intermediate code.
?: won't be of any differnece with if-else in the intermediate code either.

even if compiler wants to make differnce, it would still be hard because it's optimizing the intermediate code, not the source code.
prototype 2002-06-14
  • 打赏
  • 举报
回复
faint. ajoo, i am suprised you don't know the meaning of
magic number, since it is such a commonly-used word in
programmers' world. magic number means an explicit number
that you know nothing about it except that you know it is
a number, it won't change unless you modify that piece of
code. magic numbers hurt r&m and make the code rigid.
example:
i = 63; // here '63' is a magic number. if you are not the
author, you don't know why it is '63', what '63' means here.
all you can probably say is something like: well, '63'
somehow "magically" makes the code work.
that (hopefully) shows the basic idea. some improved versions
of magic number include adding a comment and replacing the
number with a macro.

go back to your example in your first post, the portability
problem will not exist if he does it like this:

if sizeof(T) > sizeof(int), use pass-by-ref
else use pass-by-value

will that cause any difference in semantics on different
platforms?

cloudwu 2002-06-14
  • 打赏
  • 举报
回复
shared_ptr 内部是引用计数来实现的, 在我很在意增减计数的消耗时,
这不能接受. 这也正是我曾经做过的一个东西非常在意的地方.
当我用传递的语义实现时, (当然同时还特别做了特别的内存分配
等等配合的代码) 整个程序的速度提高了一倍多.

同时为了效率, 我还特别要区分另外一种拷贝. 就是复本肯定比原始对象
先释放. 就是对象复制出去, 但是只由自己本身来维护生命期.
比如 Object a 拥有一些内部数据, 他复制给 b (Object b=a) 的时候,
一部分数据仅仅需要复制指针就够了. a 的副本 b 实际是一个 POD 的类型.

当我有这些特殊的要求 (其实都是因为效率) 使用 C++ 本身的 STL
就不能满足要求, 还要自己再写很多东西, 这很让人苦恼 :(

关于上面提到的优化. 公认的优化做的很好的 VC
也没能把 ? : 优化到 && || && 的水平, 这点可以查看 asm 代码.

至于第2点. 写个简单的例子
struct { int a,b } f;
f.a=1,f.b=2;

和 f.a=1; f.b=2;
你认为优化结果是一样的吗? 不一样. (这个例子过于简单, 可能我的结论
并不正确, 但是简单的用 , 取代 ; 的确在很多时候能加速速度)
一般编译器是以语句段来优化的, 然后在在语句段间来合并一些不必要的操作

就我的经验来说, 编译器在一条语句内做的优化是最好的. 而合并两条语句
要差一些.

当然, 在几个时钟周期的差别并无伤大雅的时候, 还是少写晦涩的长语句的好


cloudwu 2002-06-14
  • 打赏
  • 举报
回复
我也认为我应该是错的. 不过曾经的确见过编译器干一些愚蠢的事情.
或许是看错 ;)
另外, 同样是 VC, 当编译 .c 和 .cpp 时, 优化的结果也不太相同.
简单的把 .c 改名为 .cpp 时, 似乎能优化的更好一些.
当然我指的同样是 release version.
ajoo 2002-06-14
  • 打赏
  • 举报
回复
Thanks, I'll try.
don't think compiler cannot optimize (N>0)?(a):(b) , too stupid bah?

"而且表达式写成一行, 跟多行写优化的效率也不一样"?????
don't understand.

I do like your concern about the overhead of copying. that's always a heachache in C++.
But for vector, why don't you just use ref, pointer, shared_ptr?


prototype:
it won't be so easy for me to find a number that happens to cause pass-by-ref/pass-by-val diff for a given T on two given platforms. I don't disagree.
but when I say magic number, it's a number that you choose which will NEVER cause such problem for ANY T and ANY platform.
is that magic enough? :)
prototype 2002-06-14
  • 打赏
  • 举报
回复
faint. you read my post again, ajoo. i am against using magic numbers... you totally misunderstood me...
prototype 2002-06-13
  • 打赏
  • 举报
回复
> 我认为 "my be pass-by-ref on one platform, while pass-by-val on
> another one? " 并不是问题.

no, if it was so, depending on the actual type of the object, it could be very troublesome, because you have completely different semantics here.
ajoo 2002-06-13
  • 打赏
  • 举报
回复
Oh? why? protected is bad? what does he propose? base class, subclass do have tight coupling, that's not the fault of "protected" yah.
cloudwu 2002-06-13
  • 打赏
  • 举报
回复
刚才刚起床, 没仔细看帖子的前面部分 :) (而且英文水平现在还赶不上一
中学生 ;)

我那段代码并不是实用的, 我一次也没在项目里用过, 只是当初学习时, 练手用的. 如果实用可能需要更多的考虑, 但是在解决 type size 问题上, 应该没有错.


我认为
"my be pass-by-ref on one platform, while pass-by-val on another one? "
并不是问题. 从对象的角度讲, 内部是值还是引用并不重要.
接口在所有平台上是统一的就够了, C++ 就不是 2 进制可移植的.


prototype 2002-06-13
  • 打赏
  • 举报
回复
afaics, no, unless he used magic numbers (i don't think he would if he is experienced). then it is the magic numbers, not 'sizeof', that cause nonportability.
huxw 2002-06-13
  • 打赏
  • 举报
回复
原来是酱紫,放弃了好像也不是什么大不了的事情哦。呵呵

关于trick,我的意见是,自己不写;别人写好的我就用。 ;))
一种语言,背负了太多历史包袱的时候,他就会在新特性的选取上非常谨慎(我还记得b.s.把protected引入C++看作是设计中非常失败的地方)。所以语言不足的地方,用库来不足,是有C++特色的社会主义。
huxw 2002-06-13
  • 打赏
  • 举报
回复
哦?让我不明白的是酱紫

请看is_class.hpp中的第33行,给了一个地址是吧,是google上新闻组的存档。从这个地址我们可以看到一个讨论is_enum的线索。如果看过这个线索的前几片帖子,就会看到有人提到C++标准14.8.2节的内容,如果你恰好有C++标准的话,你就可以翻到那一页,然后确认一下。我确认过了,你呢?

既然is_class是符合标准的实现,那么is_enum就是符合标准的实现,是吧 ;)
ajoo 2002-06-13
  • 打赏
  • 举报
回复
这是什么典故?
go to that C++ death thread. search for "give up programing".

水果刀? with gj, although you don't have meta-programming, specialization, you can do everything else. And much neater.
Actually, I feel that mp and specialization are something specific to C++. They could make your code quite messy. you don't need them in Java.
prototype:
I agree with you. Actually I feel some of the template tricks are just patches made by the smart programmers. without language support, traits can never be perfect.

加载更多回复(59)

70,023

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧