游戏开发论坛

 找回密码
 立即注册
搜索
楼主: death

大家写engine的,用stl还是自己写?

[复制链接]

89

主题

822

帖子

847

积分

高级会员

Rank: 4

积分
847
发表于 2005-7-6 12:03:00 | 显示全部楼层

Re: 大家写engine的,用stl还是自己写?

拿去年一件事情来说,当时我还在用std::string 实现一个脚本解析引擎。但是后来发现同一个字符串有可能在内存中存在N个,比如 "int" "function" "temp"等等。于是就想到把所有的script 载入,接着tokenlize 然后根据每个token的hash(key, 字符串地址)来保存,脚本所牵涉的字符串分配的时候首先计算字符串的哈西值,然后检索hash_table ,如果已经存在,直接返回这个字符串地址,如果不存在,则再创建。 字符串hash的算法复杂度很小很小,且脚本约定全部使用小写,连tolower,toupper也都免了。最后的结果也证明,这样做效率很高。而且引发一个思路,这样分配的同内容字符串地址在运行期是唯一的,那么对资源的管理,确保资源读取的唯一性上也很方便,一般是判断资源文件名是否已经存在,后来可以就直接根据字符串地址的hash(资源路径字符串地址 ---> 资源对象)来判断资源是否已经读取。地址的hash是再快不过的了。

问题来了。我需要修改整个项目中所有的std::string , 所有的new char  所有的delete p(字符串指针) 操作! 所有的str+str2 这样的东东。。。。。




我不是很明白你的意思,但是我估计可能是这么回事,你一开始用了std::string来解析脚本文件,然后觉得这种方法不好,后来改用hash表来检索脚本。然后你觉得是std::string不够灵活,这有点牵强。呵呵,我是这么觉得的,可能我的理解不对。

我还是谈一谈我对std::string的看法和理解,STL都是有源代码的,只不过大师们的编码风格太怪异了,看他们的代码比较费劲。

STL不会使用任何C或者C++的库函数,也更不会使用操作系统应用接口函数,当然,唯一与系统打交道的是构造器,不同的编译器STL内中的构造器汇编出来可能会不一样。

std::string里面究竟封装了什么?封装了2个东西,一块静态的内存空间和一个指针。也就是说std::string在使用时是静态的连续的。只有当长度变大时,就是原来的空间无法满足现有的字符串内容时才会分配新的地址。同时要注意的是这里仅仅是变大,如果字符串变小了,不会重新分配一个小的地址空间。也就是说std::string只会越来越大不会越来越小,直到最后释放。

也就是说std::string是一个轻量级的MFC中的CString,std::string主要的用途就是用来处理字符串的查找比较替换等等常见操作,比如你想把字符串中的空格都去掉,那么用std::string要比char *,wchar *要方便一些。而且std::string也重载了一些操作符,你可以把它当字符数组使用[]来检索,也是很方便的,这个效率不会太差,因为本身也就是指针操作,还避免了越界。如果你对这个越界的检查损失的效率感觉有点舍不得,那你就把那段代码注释掉吧。如果你仅仅就是用个地址存放一下字符串,不对字符串作很多的操作,那么用char *,wchar * 就可以了,也没有必要用std::string。

再说hash表,STL据我了解是没有hash表的,有些版本的STL中增加了hash表,比如VC++.NET(VC7.1)中就有hash_set和hash_map,但是不在std命名空间中,而是在stdex命名空间里。我要说的就是VC++.NET中的hash表算法。

VC++.NET中的hash值有4个函数,分别是std::base_string(也就是std::string),const char * ,const wchar *和其他类型,对于其他类型,hash值算法非常简单就是将其转换成整型然后和_HASH_SEED异或一下。

#define _HASH_SEED (size_t)0xdeadbeef

也就是说hash函数有专门针对std::string的算法,当然也是比较简单的,如果对这些hash值的算法不满意,可以完全替换掉,写一套新的或者增加新的。

对于其中要注意的是const char * 和char *的区别,平时我们可能在其中转换来转换去的并不在意,但是,在使用VC++.NET的hash表时有可能会把char *当成其他类型来处理,会出现明明两个相同的字符串怎么hash值不一样的情况。

再说一下STL中的比较大小,STL经常会判断2个变量是否相等,但是我们印象中很难想象比如我们自定义的类型怎么比较大小。STL使用一个叫comparator的玩意(比较器?)来比较大小,其实就是一些隐含的运算符,都定义在#include<functional>中。

同时hash表中使用的是向量std::vector来存储hash表的,这个跟std::string机制一样,也是变长度的。


上面说的是我对STL的一些理解,不知道对不对,欢迎大家指教,至于说好不好用,愿不愿意用,那是个人喜好,不强求。

89

主题

4036

帖子

4132

积分

论坛元老

Rank: 8Rank: 8

积分
4132
发表于 2005-7-6 15:49:00 | 显示全部楼层

Re: Re: Re:大家写engine的,用stl还是自己写?

kypck: Re: Re:大家写engine的,用stl还是自己写?


所谓出生牛犊不怕虎,呵呵,装老鸟的话,就不要什么东西都一棒子打死,更不要进行人生攻击。打倒别人证明自己高明是很可笑的。


很多东西都不是被打死的。更别说一棒子了。通常都是自己死掉的。

31

主题

630

帖子

635

积分

高级会员

Rank: 4

积分
635
发表于 2005-7-6 17:43:00 | 显示全部楼层

Re:大家写engine的,用stl还是自己写?

STL可能没有hash表吧,好旧不用了。
可他不是有个map吗?
不会没有吧,这个太基本了。

89

主题

822

帖子

847

积分

高级会员

Rank: 4

积分
847
发表于 2005-7-7 12:01:00 | 显示全部楼层

Re:大家写engine的,用stl还是自己写?

哈哈,那就继续说map

std::map和std::set采用的都是红黑树,都是基于二叉树std::_Tree

满足下列条件的二叉搜索树是红黑树

1 每个结点要么是“红色”,要么是“黑色”(后面将说明)
2 所有的叶结点都是空结点,并且是“黑色”的
3 如果一个结点是“红色”的,那么它的两个子结点都是“黑色”的。
4 结点到其子孙结点的每条简单路径都包含相同数目的“黑色”结点
5 根结点永远是“黑色”的

但std::map不是标准的红黑树,而是经过了改造。他的检索的复杂度是O(log2N),插入的复杂度也是O(log2N),删除的复杂度还是O(log2N),注意这里的2是对数的底,没办法打出来。也就是说,对于10个元素,查找其中一个最多需要4次(2的4次方16),100个元素查找最多7次(2的7次方128),1000个元素10次,元素越多,优势越明显,而且比较稳定,不像hash函数如果hash函数设置的不好冲突过高,遇到运气差,那你就死了。

其实就有点像2分法,std::map把大的放一边,小的放一边,查找的时候,如果比当前的节点的值大就往大的树枝方向找,如果小就往小的树枝方向找。

这是我对std::map的理解,至于他跟红黑树,平衡二叉树有什么具体的区别,我还真没弄的十分明白。

在使用的时候,要注意的是删除元素,std::map不像std::list,std::list删除时是比较安全的,我们删除了一个元素,只要重新获得一下iterator(迭代器?),那么这个iterator就是可操作的,但是如果是std::map删除了一个元素iterator不一定可操作,因为list是循环双向链表,有一个空的head,对这个空的head怎么操作前移后移都没问题,但是std::map前移后移就容易出错,所以删除元素后重新获得的iterator一定要判断一下是否有效。

9

主题

266

帖子

266

积分

中级会员

Rank: 3Rank: 3

积分
266
发表于 2005-7-7 18:16:00 | 显示全部楼层

Re:大家写engine的,用stl还是自己写?

这篇帖子跟到45层,只有 bigbook2000 的上面2篇看得舒服。

9

主题

266

帖子

266

积分

中级会员

Rank: 3Rank: 3

积分
266
发表于 2005-7-7 18:29:00 | 显示全部楼层

Re:大家写engine的,用stl还是自己写?

我不是很明白你的意思,但是我估计可能是这么回事,你一开始用了std::string来解析脚本文件,然后觉得这种方法不好,后来改用hash表来检索脚本。然后你觉得是std::string不够灵活,这有点牵强。呵呵,我是这么觉得的,可能我的理解不对。

不是觉得std::string 不灵活,是想不能通过new 来分配字符串。而必须由我指定的一个近似字符串池的结构来负责所有字符串的分配和删除。 最后找不到如何这样控制一个string 对象,但是对char* 却非常顺手。。。。

#define NEWSTR(x)  gStrPool->New((x))
char* str= NEWSTR("hello,world");

不过刚才看了你的帖子,似乎std::string 也可以做到。。。。
回家再尝试下。

31

主题

630

帖子

635

积分

高级会员

Rank: 4

积分
635
发表于 2005-7-7 19:32:00 | 显示全部楼层

Re: Re:大家写engine的,用stl还是自己写?

bigbook2000: Re:大家写engine的,用stl还是自己写?

哈哈,那就继续说map

std::map和std::set采用的都是红黑树,都是基于二叉树std::_Tree

满足下列条件的...

多谢!

23

主题

515

帖子

552

积分

高级会员

Rank: 4

积分
552
发表于 2005-7-8 12:12:00 | 显示全部楼层

Re:大家写engine的,用stl还是自己写?

我就晕~~~

33

主题

669

帖子

669

积分

高级会员

Rank: 4

积分
669
QQ
发表于 2005-7-9 14:19:00 | 显示全部楼层

Re:大家写engine的,用stl还是自己写?

我觉得楼上的说的有理,自己真的没什么时间去写一个比STL高性能的库

26

主题

324

帖子

325

积分

中级会员

Rank: 3Rank: 3

积分
325
QQ
发表于 2005-7-9 18:01:00 | 显示全部楼层

Re:大家写engine的,用stl还是自己写?

其实只要说你用不用就可以了!
每个人都有自己的理由啊!自己高兴,自作孽还不行吗?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-12-20 15:48

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表