re: 盖莫游戏引擎2.1.0发布了[未登录] Dancefire 2010-06-30 09:18
建议在google code hosting上建立一个开源项目,这样发布、源代码下载修改,bug提交都会比较容易。
re: 2个c++编译器的差异[未登录] Dancefire 2010-06-30 09:14
@ccsdu2009
如果是Dev-c++那就更惨了。Dev-C++已经5年没有更新过了。其中的gcc版本也是甚老的版本,3.4.2。能尝试着用mingw gcc 4.x以上编译一下看看么?
http://tdm-gcc.tdragon.net/ 有非官方的gcc 4.4的安装包。
re: 2个c++编译器的差异[未登录] Dancefire 2010-06-26 20:49
请检查一下你现在使用的mingw的版本。mingw当前的稳定版本是4.5.0-1。但是如果你通过mingw的windows自动安装程序(已不推荐使用) 5.1.6来安装的话,会安装3.4.5。目前比较正确的使用mingw的方法应该是下载压缩包自己解压缩到合适的位置。下一代的自动安装程序mingw-get刚刚进入alpha测试阶段,如果尝试也可。
说这些的原因是提醒注意是否是由于gcc 3.x和4.x的差异导致的不同。如果是的话,那么只需要安装最新的mingw的编译器即可,不必调整代码。
我的观点是这样:
1、如果只有5层左右if嵌套,不是什么大问题。可以用一个函数解决,看到不少代码中都是存在一个函数中有多层if嵌套。
2、如果嵌套太多,影响函数逻辑的清晰了。那么拆解函数,将功能独立的内层嵌套,拆解成独立的函数。保证每个函数中嵌套不要太多,而拆解出的函数,功能又比较独立。
3、对于需要重复写每次清理时繁琐的步骤的问题,如果确实重复、确实繁琐,可写成一个函数,每次清理前调用一下这个函数即可。不用担心调用成本,C++会自动分析,编译Release版本时,很有可能会将其视为inline。
4、假如Process和Token的每次创建过程都比较复杂,比如有多种情况要考虑,多种错误要处理,出现问题后要有多种错误处理方式。那么建议将Process和/或Token进行类封装。这样使用时,只要Process p;即可,发现错误直接return false; p会自动析构,调用相应的析构函数来清理垃圾。在这种情况下,我与第一个回复的朋友观点一致。不要担心类的成本,只要没有继承、虚函数之类的东西,类的效率与调用函数无太大差别。
5、使用异常。异常的设计初衷本就是为了解决这种现象的,避免错误处理影响了函数逻辑。如果出了错就是异常处理、清理、返回,而不会出现改正错误重新执行代码的情况,可以使用异常。这样只要出错就抛出异常,不同的错误,异常不同。函数内解决异常,不让异常出函数。这样也可以将错误处理集中起来。
如果我没有理解错,你试图用locale为ASCII的isspace来判断GBK编码的空格,对么?如果我理解正确的话,那么这不是VC的问题,而是使用上的问题。
对于C++而言,应该使用isspace(ch, loc); 这个版本,loc是类型为std::locale的变量,如果你想判断GBK的空格,那么让loc是GBK的locale,然后这个函数就正常了。
你现在使用的是C的isspace(ch)函数,这个函数使用的是默认的全局locale,你把这个全局的设为GBK,也应该可以解决这个问题。总之调用locale为默认的ASCII的locale的isspace去判断编码为GBK的字串是否是空格,逻辑上不对。
re: 我的项目Makefile文件模板 Dancefire 2009-02-25 00:23
楼主,对于几个源代码的文件,可以考虑直接用Makefile写写。但是对于真正的项目,用Makefile就远远不足了。建议楼主了解一下三个工具,autotools、CMake、SCons。使用这些工具,对于你写的这50行左右的Makefile,甚至可能可以缩减为不超过5-10行。
autotools,包括automake, autoconf之类的工具。它能够自动生成Makefile。是比较早期的Makefile替代物(Makefile不叫早期,叫原始)。不难用,很多开源软件都用它。
CMake和SCons是比较现代点的工具。相比而言,我更推荐CMake。
CMake可以跨平台,它并不直接build,而是先生成平台上习惯的Build文件,然后再用平台自己的工具进行Build。比如在Linux上,它可以先生成Makefile,然后用户直接make就可以了。而在Windows上,它可以直接生成Visual Studio的项目文件,然后用户可以用VS打开其文件进行Build。这种方式我比较喜欢,而且使用起来也非常的简单。
SCons是基于Python的,甚至配置也是,强大之处在于如果你会Python,那么可以在里面做任何事,毕竟这比automake或者makefile的shell强大太多了。但是缺陷是许久没有发展了,主要在bugfix中。而且通过google trends比较可以看出CMake比SCons似乎更有活力,发展更好。
@volnet
Boost可以称其为是一套准标准库。它项目建立的目的之一就是为未来的C++标准库提供候选方案,目前已经有将近十个Boost库成功的成为了C++标准预案。
它的优势很多,首先是代码使用现代C++的语法,因此namespace, 异常, 模板之类的C++特性会被充分挖掘利用,代码从设计、实现到文档都具有了相当高的水准。另外,由于它使用的是标准C++语法编写,因此它的可移植性非常的好。当然,针对一些存在问题的编译器,它也会进行相应的调整以尽量支持。
Boost这种优良的库,涵盖的领域很广,可以说是标准库很好的补充。另外绝大多数Boost库都不需要编译链接,大部分的Boost库仅仅include头文件即可工作。我看到国内很多人提到Boost的时候说它比较难以编译安装云云。其实没必要编译,绝大多数的库仅仅是由头文件组成的,只要include进来就可以用了。
Boost是C++强有力的工具,学习C++,除了标准语法和STL外,Boost是必须熟悉的,否则,工程上很有可能会做一些Boost已经实现很久的东西,除了重复开发外,而且你的代码的质量和可持续性比Boost差很远,造成项目质量的下降。
@volnet
呵呵,非模板类型的函数定义我们也不会需要在foo.h中include foo.cpp啊:)
在楼主的例子里面为了能够让定义和声明分开,将声明放到了foo.h中,而定义放到了foo.cpp中,这和非模板类型的函数是一样的。但是可惜这么做是无法通过的,因为模板类型函数不能够(由于没有export支持)单独编译。为了让编译通过,楼主将foo.cpp给include进了foo.h,这样实际上是将两个文件整合成一个文件了。这样编译就没有问题了,但是得小心需要把foo.cpp分离出项目,因为它不可以被编译;或者将其扩展名从.cpp改为.hpp。
实在是不推荐楼主这么分开的写,说实话这算不上是什么标准的做法,而且这样并没有太大的意义。如果非要分开,可以将定义后缀到声明后面,在一个文件里。但是分开确实没太大意义。可以研读一下boost里面的做法。
楼主,你的问题其实很简单。
你是不是把foo.cpp也放进Visual C++的项目里了?如果是的话,这样会导致foo.cpp的编译,这个编译会导致T Foo<T>::GetInstance(void)被编译实现。当继续编译main.cpp的时候,就会报告,T Foo<T>::GetInstance(void)已经有一个实例了。
解决办法很简单,把foo.cpp移出工程就可以了。只要物理上foo.h的同目录存在foo.cpp这个文件就可以了。因为foo.cpp根本没必要去编译。甚至我都不建议你称其为foo.cpp,不如叫什么foo_impl.hpp之类的文件名更合理些,这样即使这个文件在工程里面也不回导致被编译。
re: 解决TSVN的diff显示中文件不全的问题 Dancefire 2009-02-16 11:12
@金庆
嗯,凡是存在非ASCII编码的字符,都应该采用UTF-8进行文件存储。如果不使用UTF8,那么意味着使用的是系统本地编码,在Unicode诞生前,全球那么多种稀奇古怪的编码,仅仅中文,就有GB2312, GBK, GB10830, BIG5, HZ, Shift-JIS等许多编码,Subversion之类的软件根本无法猜测开发人员的机器是什么编码的,自然会出现乱码。即使像浏览器一样也来猜测也是不大可能的。Unicode/utf-8是一个非常好的解决这类乱码问题的解决方案。所以,大部分的这类软件都做到支持UTF-8,这样就可以支持全球语言了。
re: 解决TSVN的diff显示中文件不全的问题 Dancefire 2009-02-15 13:49
@LOGOS
这没有什么一般不一般的,你保存成utf8就是utf8的。保存文件的时候有一个高级保存选项,你可以选择是否使用UTF8 with signature来保存。如果代码中有非ASCII,我一般选择这个。只要是UTF8的,放到哪里都正常,包括TortoiseSVN的差异和比较。
re: 解决TSVN的diff显示中文件不全的问题 Dancefire 2009-02-15 00:03
我用TortoiseSVN好像没有这种问题,你的源文件是使用的UTF-8 with BOM么?如果没有使用UTF-8 with BOM,可能会出现乱码的问题,这应该可以理解。
re: Thread Class Dancefire 2009-02-08 22:53
封装这个作甚?是自己玩么?如果真用起来,还是建议你考虑一下很多已经作好的封装。许多出色的线程库都充分利用了C++特性,并且是跨平台的,比这个要好的多。比如,
[boost::thread]
http://www.boost.org/doc/libs/1_37_0/doc/html/thread.htmlhttp://www.stlchina.org/twiki/bin/view.pl/Main/BoostThread如果需要小巧,也有ting,也是跨平台的:
[ting]
http://code.google.com/p/ting/也有含在glibmm里面的Glib::Thread
[glibmm/threads]
http://www.gtkmm.org/docs/glibmm-2.4/docs/reference/html/group__Threads.html如果不是coding 4 fun,而是有任何使用价值,不妨停止重复造轮子,看看已有实现先。毕竟那些充分利用了C++特性,而且是跨平台的。另外需要注意的是,C++并不追求代码行数最少,而是追求效率和结构,不要陷入用最短的代码就是最好的误区。
楼主,auto_ptr<char> VersionInfo(new char[xx]);的用法绝对是错的。auto_ptr只会delete指针,而不会delete[]指针。因此VersionInfo的指针不会被释放。
针对这个问题C++09引入了一个新的库,scoped_ptr和scoped_array来替代补充auto_ptr。scoped_array就是可以处理数组的。楼主或者下载微软的2008 feature pack,或者使用boost库,就可以使用这种智能指针了。除此以外,标准还引入了引用计数型指针,如shared_ptr和shared_array。来处理超出函数范围的指针释放问题。楼主可google相关资料。
re: 也谈表达式分析和计算 Dancefire 2009-02-05 15:14
@空明流转
这是我的失误。复习了一下,BNF应该是可以构建无歧义的语法(
http://www.garshol.priv.no/download/text/bnf.html)。而EBNF构建的语法是可能出现歧义的,而且目前好像没有算法可以证明EBNF定义的语法是否是无歧义的。(
http://infolab.stanford.edu/~ullman/ialc.html)。但是EBNF肯定是可以构建无歧义的语法的。
发生歧义的时候,boost::spirit可能是按照其实现解析,可能不会报错也不会列举多种可能,具体上可以查看boost::spirit的实现,看看它是如何处理这类问题的。
re: 相似图像搜索(算法) [原创] Dancefire 2009-02-04 19:19
算法上很奇怪,求每一个块的颜色数的差。首先是无法处理经过缩放的图片,其次是无法处理整体调暗或调亮或者转色的图片,而且求的是平均值而不是常用的SSE?
为什么不考虑用离散余弦求出最显著的特征,缩小至特定大小后,使用HSV(而不是RGB)来分通道比较并且综合其结果呢?这样起码转色、缩放、JPG按照不同质量保存或者换图像格式、调明暗之类的问题基本上都可以处理的。
可以看一些关于模式识别、数据挖掘和图像处理的书,应该对上述问题都有介绍。
re: 也谈表达式分析和计算 Dancefire 2009-02-04 19:01
@陈梓瀚(vczh)
这倒不是Spirit的问题,Spirit实现的是EBNF,BNF(EBNF)不可以处理有歧义的语法。其实很容易理解,BNF是用于编译程序代码的,程序代码是不允许出现歧义的,不然编译器将无法解析正确结果了。
你说的歧义问题,是处理自然语言中经常碰到的情况,可以对所有可能构成生成一个有向无环图,然后用概率预测最可能的通路。
@王博炜
那可得多了解了。Boost是C++程序员必备技能之一。Boost的组织内有很多都是C++委员会的成员,库的内容涵盖了程序设计的方方面面,虽然不完全,但是很多东西都用得到。而且Boost完全按照C++标准撰写代码,它是跨平台的,基于Boost的代码,可以很方面的移植到其他系统。另外Boost基本全部由头文件组成,因此绝大多数库都不需要链接任何东西,直接include到源文件就可使用。Boost内包含了很多成员库,其质量相当高。从网络通讯、序列化、线程到正则表达式、内存管理、图像处理、算法等等,很多东西都可以使用boost来简化设计。
re: 对基本类型的再包装,方便了移植 Dancefire 2009-02-04 09:48
@梦在天涯
不是自定义的UInt32,而是标准中的uint32_t或者,int32_t之类。自定义的类型是无法保证这一点的。
是否使用这类确保跨平台一致性的类型,关键在于你的应用在使用这些类型的时候是否关注其大小。比如你仅仅是进行个for-loop,或者简单的计数或者确定数字不是很大的计算,那自然无所谓了。
但是比如你要把一个数字以二进制格式存储到硬盘上,或者要进行网络通讯,其内容是某结构体等,或者某些变量需要至少多少位的空间才能够满足需求。碰到这类比较关心实际占用空间大小的问题,而且系统是跨平台的,那么就需要考虑使用标准中具有跨平台一致性的类型了。那些是由编译器会保证跨平台大小一致的。
re: std::map于vc6下的使用bug Dancefire 2009-02-03 14:07
goodname说的对,凡是形如 xxx<xxx<xxx>>这种模板嵌套的情况,c++当前的标准对此会报错,因为>>解析的问题。当前的解决办法是在两个相邻的>>之间添加一个空格。
C++09已经修复了这个问题,在今年即将公布的新标准中,你这样定义是没有任何问题的。不同的编译器有不同的处理。自从C++委员会主席加入vc团队后,vc一直在标准兼容上处于领先地位。特别是c++/cli,允许上述写法,C++自然也继承了这个特性,所以你在vs2005下编译有可能通过。当然vc6这种老掉牙的东西是不支持的。
但是你不应该以是否编译通过为撰写代码的衡量标准,应该按照标准兼容的方式写代码。因此目前而言,为了兼容C++标准,你应该在两个大于号之间加空格,以保证这段代码可以在其它编译器下可以工作。
re: 对基本类型的再包装,方便了移植 Dancefire 2009-02-03 12:56
@true
那就不使用第三方库好了。boost的头文件可以直接拷过来用,修改一下当成自己的,算不得第三方库了吧?或者从mingw中把stdint.h拷过来也行,那个是针对win32平台修改过的stdint.h。就一个头文件而已,也算不得第三方库吧?对于这个头文件而言,VC6是肯定兼容的,最多稍微修改一下不会太费力气。
对于类型而言,应该使用标准所制定的跨平台一致性类型。但是vc不支持,因为我们添加个头文件让其支持标准。这样就可以保证和所有支持c99系统的一致性了。比如linux,甚至freebsd或者netbsd,或者darwin/macos。
所以,在已存在标准这个前提下,那么问题应该描述为如何为vc补全所需标准的内容。这很简单,遵循标准定义,或者直接那别人已经定义好的头文件过来就ok了。也不依赖任何第三方库。
关于你说的__VA_ARGS__,也是C99标准的一部分,所有支持c99的编译器都支持,包括gcc。
http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.htmlVC2005开始以后都支持了。
http://msdn.microsoft.com/en-us/library/ms177415(VS.80).aspx
因此之前的版本如果不支持,那应该设法为vc6定义一个__VA_ARGS__的宏,来使之支持相应的标准。
原则就是,凡是在标准中已经明确定义的东西,那么谁不支持标准,就让谁符合标准。而不要自己重复造轮子,因为你无法保证你定义的类型在多系统下兼容,毕竟你接触和使用的系统有限。何不只让不符合标准的符合标准,至于其他支持标准的系统,自然不用你来操心。
re: 对基本类型的再包装,方便了移植 Dancefire 2009-02-03 12:00
@true
我的回复中已经提到,因为微软尚不支持c99标准,因此vc用户享受标准提供的便利会有些麻烦。
但是我也提到了,<cstdint>已经被提到TR1并且进而提到了c++09标准中了,因此,各大编译器已经都开始支持<cstdint>了。对于gcc用户自然没问题。对于vc用户,有很多
种办法可以提前使用c++09的一些库:
1) 下载微软vc2008 Feature Pack,里面提供了TR1的实现,其中包含我提到的头文件。
2) 更简单一些,安装boost,使用<boost/cstdint.hpp>文件,里面也是按照TR1标准/c99标准实现的跨平台统一的类型文件。
3) 使用第三方的c++标准库,如apache的stdcxx,里面也基本上支持了TR1,包含了我说的头文件。
因此完全不用自己定义。更何况自己定义的很难符合跨cpu,跨系统的统一性。而我说的这些实现,由于按照标准,已经支持几十种系统和cpu的组合了,为什么还要自己定义呢?拿来用就好了。
如果仅仅是担心vc和其它环境不兼容,那大不了从mingw中把stdint.h拷过来,然后按照vc环境改一改就可以了。这样在vc环境下include这个头文件,其它环境下使用标准头文件。除了微软外的编译器基本上都支持c99,因此不用担心其他平台的兼容性。
re: 对基本类型的再包装,方便了移植 Dancefire 2009-02-02 21:18
在1999年以前,你这么做是合理的。但是1999年C99标准推出以后,这样做就已经不合理了。你应该使用C99的标准头文件<stdint.h>,如果是C++的话,应该使用<cstdint>。
在stdint.h中,标准明确要求定义:
int8_t;
int16_t;
int32_t;
int64_t;
和
uint8_t;
uint16_t;
uint32_t;
uint64_t;
有关C99的stdint.h的信息请参考wikipedia上的介绍:
http://en.wikipedia.org/wiki/Stdint.hhttp://www.opengroup.org/onlinepubs/009695399/basedefs/stdint.h.htmlc++委员会已经把cstdint纳入TR1中,并已经列入c++09的标准中,今年内就会称为c++标准的一部分。
这些类型的定义,将有所用的编译器和库保证其平台间一致性。gcc和unix下很多C或者C++编译器的用户已经随时可以使用<stdint.h>或者<cstdint>,因为gcc支持c99标准,并且libstdc++也包含了<cstdint>。至于Windows用户而言,稍有不幸,因为微软的编译器不支持c99标准,所以没有<stdint.h>这个文件,这也可能是楼主不知道这个文件的主要原因。但是没关系,boost库提供了tr1的完整实现,其中自然包含了<cstdint>,只要引入<boost/cstdint.hpp>就可以使用上述类型而不用担心跨平台性。当然,一如既往,boost提供了更多的可移植性基础类型的定义。
http://www.boost.org/doc/libs/1_37_0/libs/integer/cstdint.htm请楼主参考这些信息修改文章,毕竟在标准可用下,使用标准更合理。