可冰

冰,是沉睡着的水......

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  37 随笔 :: 5 文章 :: 94 评论 :: 0 Trackbacks

2006年7月13日 #

我已在百度空间新建博客,欢迎大家来访
posted @ 2006-07-13 15:17 可冰 阅读(876) | 评论 (15)编辑 收藏

2006年6月27日 #

http://post.baidu.com/f?kz=109415855
posted @ 2006-06-27 22:14 可冰 阅读(249) | 评论 (0)编辑 收藏

2006年6月23日 #

Apache中如何配置才能使所有请求都由某一个页面处理。即:
在http://some.thing.com/下有一个处理器,叫handler.xxx,那么类似下面的

URL请求,都由此处理器接收并处理。
http://some.thing.com/handler/other/string/etc
也即上面的相当于
http://some.thing.com/handler.xxx?other/string/etc


posted @ 2006-06-23 19:41 可冰 阅读(345) | 评论 (0)编辑 收藏

网络的并发连接数到底是由什么限制的?即哪些因素是最主要的,难道不能解决吗?
现在一个好的网络程序,通常最多能达到多少的并发连接数?

posted @ 2006-06-23 19:40 可冰 阅读(431) | 评论 (2)编辑 收藏

2006年4月21日 #


        在C/C++中,变量及函数的定义一般都是在.h/.hpp文件中说明原型,而在对应的.c/.cpp文件中来进行实现.
        这种情况下,头文件最终是给用户使用的,以便让用户了解有哪些接口可以使用;而.c/.cpp文件是开发者使用的,以便让其它开发人员了解它的实现逻辑.因此这两个文件中肯定都是需要详细的注释的.在.h/.hpp文件中,主要说明函数的使用方法,如参数的意义,返回值的定义等.而.c/.cpp文件中,主要说明函数的实现逻辑等.

        不知道上面的做法是否合适.请大家指正!
        另外,大家在实际编程过程中是如何做的?

        事实上,我自己在实践过程中却总是偏向于把注释写到一个地方,或者注释原型,或者注释实现(前者比较多),甚至干脆两边都写一样的(但这样的话内容经常会不一样).这样的方法让我在编程过程中吃尽了苦头哇.

posted @ 2006-04-21 15:20 可冰 阅读(540) | 评论 (3)编辑 收藏

2005年11月28日 #

前几天看了荣耀老师对Bjarne先生的访谈,其中Bjarne说的一句话我印象特别深刻:

荣耀:一个有点儿八卦的问题。C++标准委员会中有中国人吗?有中国人向C++标准委员会递交过提案吗? 

Bjarne我想不起来最近的提案和中国人有关。委员会中有一个IBM的新代表,姓王。我猜他是中国人,但我还不认识他。 

考虑到中国有那么多人在从事计算机工作,一直很奇怪为什么看不到你们对C++0x标准化工作的参与

我不知道这究竟是怎么回事。

自从我前段时间订阅了Google新闻组中的comp.lang.c、c++论坛,我看到的所有帖子几乎都是在讨论C++0x标准的。给我的感觉就像这里面都是标准委员会的成员或那一类的高手,我也没有参与过任何讨论,甚至也没细心去看看相关的问题。我也很关注C++0x标准的制定,但却从来没有参与进去或想过要参与进去,这又是为什么呢?

我想大多数的朋友也可能是这样的情况吧。并不是不想参与,而是从来没有想到过。我想这一定和我们的教育有关。我们被培养为只接受而不用去参与,我们只去被动的学习新的知识,而从没有想过去主动的参与到新知识的产生的过程中。

不过,现在情况应该改变一下了,至少我们已经看到Bjarne先生的提醒了:我们要参与进去!不仅仅是参与C++0x的标准制定的问题,而是思想习惯的问题。

朋友们,我们要改变现在的这种思维方式了,要参与到更多的活动中去。

posted @ 2005-11-28 13:51 可冰 阅读(557) | 评论 (5)编辑 收藏

2005年11月22日 #

//自己翻译的,本想整理一下,但一直没时间,现在就这样放上来吧,有错就批,别客气,呵呵。

C++编码规范

一、组织与策略问题

If builders built buildings the way programmers wrote programs, then the
first woodpecker that came along would destroy civilization.
----Gerald Weinberg
在C和C++的主要传统中,我们认为是一种零基础的习惯.第0条是一个根本的指示,它涵盖了编码规范中我们认为是最基本的建议.
在这介绍性的一节的其余部分中,我们精心选取了其中的少量问题加以阐述,这些大多与编码本身无直接关系,但却是写出可靠代码的基本工具和技术.
在这一节中我们认为最有价值的是第0条不要因小失大.(或:知道什么不需要规范化.)

0. 不要因小失大. (或:知道什么不需要规范化.)

摘要

仅说必要的话:不要坚持个人品味或陈旧的习惯.

讨论

真只是个人品味且不影响正确性或可读性的结论不属于编码标准.任何专业程序员可以很容易地读写稍微不同于他所习惯的格式的代码.
在每个源文件甚至每个工程中都要用一致的格式,因为在几种不同编码风格的代码片段中跳转是很不协调的.但是不要企图在不同项目或公司中坚持一致地格式.
下面是几条通用的结论,这里重要的不是去制定规则,而只是要保持与你维护的文件的风格的一致:
不必明确指定要缩进多少,但要缩进以突出结构:用你喜欢的任意数量的空格缩进,但至少要在同一文件中保持一致.
不必强行保持特定的行长度,但要保持行具有可读性:用你喜欢的任意长度的行长,但不要太长了.研究表明十个单词以内的宽度对眼睛跟踪是最理想的.
不要过度制定命名规则,但要用一致的命名约定:仅有两点必须要做的:a)决不用"隐秘的"名称,也即以一个下划线开头或包括双下划线的名称;以及b)总是用字母全部大写的单词命名宏并且决不要考虑定义一个常用或缩写单词的宏(包括常用模板参数,比如T和U;以#define T anything定义任何东西是极其不好的做法).此外,要用一致的有意义的名称,并按照文件或模块的约定.(若你不能决定你自己的命名约定,试试这种方式:以各单词首字母大写方式命名类、函数和枚举(LikeThis);命名变量时在前者基础上小写第一个单词的首字母(likeThis);命名私有成员变量时在前者方式之后再加一个下划线(linkThis_);以全大写并用一个下划线连接各单词的方式命名宏(LINK_THIS).)
不要规定注释的风格(除非有工具解析特定格式的注释生成文档),但要写有用的注释:如果可以的话以代码来代替注释(见第16条).不要在注释中重复代码;它们不能被同步维护.要写解释方法和基本原理的启发性的注释.
最后,不要试图坚持陈旧的规则(见例3例4),即使它们曾在旧编码规范出现过.

例子

  • 例1:括号的放置.下面的几种没有任何可读性上的差异.
    void using_k_and_r_style() {
    // K&R风格
    }

    void putting_each_brace_on_its_own_line()
    {
    // 括号独占一行
    }

    void or_putting_each_brace_on_its_own_line_indented()
    {
    // 括号独占一行并缩进
    }
    任何专业程序员都可以不费力地读写上面所列的任何一种风格的代码.但要保持一致性:不要随意的或以晦涩的嵌套方式放置括号,试着去遵循各文件中已有的风格.在本书中,我们的括号有意识的在排版的约束中以最好的可读性的来放置.
  • 例2: 空格与制表符.由于编辑器对制表符解释的不同,它可能被误用,或被理解成凸出,或无缩进,这种情况下一些团队合理地选择禁用制表符.其他同样有名望的团队则合理地允许制表符,而采用纪律来避免其潜在缺点.只要保持一致性:当团队成员维护其他人的代码时,如果你允许使用制表符,确保不要以代码清晰度和可读性为代价(见第6条).如果你禁用制表符,允许编辑器在读入源文件时将空格转换成制表符,以便用户可以在编辑器中使用制表符;但要确保写回文件的时候将它们还原为空格.
  • 例3: 匈牙利命名法. 将类型信息合并到变量名称中的命名方式为类型不安全的语言(尤其是C)带来了一些混合的作用.但这种命名法在面向对象语言中没有好处(只有坏处),尤其在泛型编程中是根本不可能的.因此,不会有哪个C++编码规范会要求用匈牙利命名法,C++编码规范可能合理地将其排除在外.
  • 例4: 单入口,单出口("SESE"). 历史上,一些编码规范要求每个函数有且仅有一个出口,也即一个返回语句.这样的要求在支持异常与析构函数的语言中是过时的,在这些语言中,函数通常都会有许多隐式的出口.取而代之的是,按照像第5条那样直接提倡更简短的函数的标准,这样会很自然地具有更容易理解代码和把握错误的特性.

    参考

    [BoostLRG] · [Brooks95] $12 · [Constantine95] $29 · [Keffer95] p. 1 ·
    [Kernighan99] $1.1, $1.3, $1.6-7 · [Lakos96] $1.4.1, $2.7 · [McConnell93]
    $9, $19 · [Stroustrup94] $4.2-3 · [Stroustrup00] $4.9.3, $6.4, $7.8, $C.1
    · [Sutter00] $6, $20 · [SuttHysl01]

    1. 以高警告级别干净地编译

    摘要

    将警告铭记于心:使用你的编译器的最高警告级别.要求干净(无警告)的构建.理解全部的警告,并通过修改代码消除警告,而不是通过降低警告级别.

    讨论

    编译器是你的好朋友.若它由于一个特定的结构而发出一个警告,通常你的代码含有潜在的问题.
    成功构建应该是干净的(无警告的).如若不是这样,你将会很快养成快速浏览输出结果的习惯,进而你将错过真正的问题.(见第2条)
    消除警告: a)理解它;然后b)更改你的代码去消除警告并让你想让它所做的事情对人和编译器都更清楚.
    一定要做这一步,即使一开始程序看起来正确运行了,或者即使你肯定警告是良性的.即使是良性警告也可以使后面的指出真正危险的警告变得隐晦.

    例子

  • 例1: 第三方头文件.你不可能去修改一个引起(或许是良性的)警告的库头文件.因此你要在你自己的头文件中包含原始头文件并仅在这个头文件的作用域内选择性的屏蔽掉这些烦人的警告,然后在你其它的项目文件中包含你的这个包装过的头文件.例如(注意这里的警告控制语法在编译器间是不同的):
    // 文件: myproj/my_lambda.h -- 包装Boost的lambda.hpp
    // 总是使用这个文件,而不直接使用lambda.hpp.
    // 注意: 我们的构建现在自动检查: "grep lambda.hpp ".
    // Boost.Lambda产生我们所知道的无害的编译警告.
    // 当作者修正它时我们将移除下面的#pragma语句,但是这个头文件仍将存在.
    //
    #pragma warning(push) // 仅屏蔽这个头文件
    #pragma warning(disable:4512)
    #pragma warning(disable:4180)
    #include #pragma warning(pop) // 恢复原来的警告级别
  • 例2: "未使用过的函数参数."检查以确保你真的不打算用这个函数参数(例如:它可能是占位符以便将来扩展,或是你代码中从未用到但却是必需的标准化函数签名的一部分).如若它不是必需的,只要删除这个函数参数就行了:
    // … 不使用提示的用户自定义分配器内部 …

    // 警告: "unused parameter 'localityHint'"
    pointer allocate( size_type numObjects, const void *localityHint = 0 ) {
    return static_cast( mallocShared( numObjects * sizeof(T) ) );
    }

    // 新版本: 消除警告
    pointer allocate( size_type numObjects, const void * /* localityHint */ = 0 ) {
    return static_cast( mallocShared( numObjects * sizeof(T) ));
    }
  • 例3: "变量定义了但却从未使用."检查确保你真的不想引用这个变量.(一个基于栈的RAII对象经常引起这样的不合理的警告,请见第13条.)如若它不是必需的,通常你可以插入一个变量自求值的表达式使编译器安静(这一求值不会对运行时速度有影响):
    // 警告: "变量'lock'定义了但却从未使用."
    void Fun() {
    Lock lock;

    // …

    }

    // 新版本: 消除了警告
    void Fun() {
    Lock lock;
    lock;

    // …

    }
  • 例4: "可能使用了未初始化的变量."那就初始化这个变量(见第19条).
  • 例5: "丢失返回语句."即使你的控制流永远也不可能到达函数的末尾,编译器有时也会要求有一个返回语句(例如无限循环、异常抛出语句以及其它类型的返回语句).这也许是一件好事,因为有时你只是认为控制流不会运行到末尾.例如无default的switch语句没有修改的弹性,因些要有一个default语句执行assert( false ) (另见第6890条):
    // 警告: 丢失"return"
    int Fun( Color c ) {
    switch( c ) {
    case Red: return 2;
    case Green: return 0;
    case Blue:
    case Black: return 1;
    }
    }

    // 新版本: 消除警告
    int Fun( Color c ) {
    switch( c ) {
    case Red: return 2;
    case Green: return 0;
    case Blue:
    case Black: return 1;
    default: assert( !"should never get here!" ); // !"string"的值为false
    return -1;
    }
    }
  • 例6: "有符号/无符号不匹配."有符号数与无符号数之间的比较与赋值通常不是必需的.改变参与比较的变量的类型以使满足类型匹配要求.最坏情况下,插入一个显式转换.(由于编译器为你插入这样的转换,也会警告你它所做的,所以你最好不要让它出现.)

    例外

    有时编译器可能发出一个厌烦的甚至欺骗性的警告(比如纯粹的扰乱信息),但没有可提供的方法去消除它,而且去修改代码去消除它可能是不可实现的或是徒劳的工作.在这些罕见的情况下,作为一个团队决策,除去这个只是无聊的警告的烦人的工作是:仅使特定警告无效,并尽可能是局部性的,并写一个清晰的注释文档说明为什么这样做是必要的.

    参考

    [Meyers97] $48 · [Stroustrup94] $2.6.2

    2. 使用自动构建系统

    摘要

    按(单个)按钮:使用一个无需用户参与的全自动("一键触发")构建系统.

    讨论

    一个一键触发式构建方法是基本的.它必须进行可靠的和可重复的转换,将你的源文件转换为可交付的程序包.有很多自动构建工具可以使用,没有理由不去用它.挑选一个,使用它.
    我们已见过一些忽视了"一键触发"式要求的组织.一些人认为随处点几下鼠标,就可以运行一些工具来注册COM/CORBA服务,或通过手工定制的一个合理构建过程拷贝一些文件.但是你没有时间和精力可以浪费在一些机器能做得更好更快的事情上.你需要一键触发式的自动化的和可靠的构建.
    成功的构建应该是没有任何警告的(见第1条).理想化的构建不产生扰乱信息,而仅是一个日志消息:"构建成功完成."
    有两个构建模式:增量构建和完全构建.增量构建仅重建自上自增量构建或完全构建以来被修改过的文件.推论:两个连续的增量构建中的后者应该没有任何输出文件;如果有的话,你可能有一个依赖环(见第22条),或者你的构建系统执行了不必要的操作(例如生成不合理的临时文件而只是丢弃它们).
    一个工程可以有不同形式的完全构建.考虑用一系列本质的特征确定你的构建的参数;很可能候选者就是目标式体系结构、调试和发布、或更广(基本文件和全部文件和完全安装).一个构建设置可以创建一个产品的基本的可执行文件和库,另一个可能也创建一些辅助文件,一个完全充实的构建也可能创建一个包含你所有文件、可重发布的第三方库和安装代码的安装程序.
    随着工程的进行,没有自动构建的花费也在增长.如果你一开始没有用,你将浪费很多时间和资源.更糟糕的是,随着自动构建成为无法抵抗的需求,你将会有比项目一开始更多的压力.
    大项目可能有一个"构建师/主管",他的工作就是照料构建系统.

    参考

    [Brooks95] $13, $19 · [Dewhurst03] $1 · [GnuMake] · [Stroustrup00] $9.1

    3. 使用一个版本控制系统

    摘要

    好记性比不上烂笔头:使用一个版本控制系统(VCS).决不要让检出的文件保留很长时间.一旦你的更新的单元通过测试就尽快检入.确保检入的代码不会破坏整个构建.

    讨论

    几乎所有不平凡的工程都需要一个以上的开发者和/或超过一周的工作量.在这样的工程中,你将需要比较同一文件的历史版本以确定变化是什么时候(和/或被谁)引入的.你也将需要控制和管理源代码的变化.
    当有多个开发者时,几个开发者很可能会在同一时间对同一文件的不同部分进行并行地更改.你需要工具以自动进行文件的检出和恢复,以及在某些时候对并发编辑的合并.VCS自动操作和控制检出,恢复以及合并.VCS比手工做的更快更准确.而且你不用花时间每天的去摆弄那些重复性的工作,你有软件要写.
    不要破坏构建.在VCS中的代码必须总是可以成功构建的.
    存在很多的版本控制系统可供选择,没有理由不去用它.最便宜和流行的是cvs(见参考).它是一个灵活的工具,具胡TCP/IP访问特性,可选择性的提高安全性(通过用安全外壳SSH作为后端),卓越的脚本管理,甚至有图形接口.许多其它VCS也将cvs作为标准去效仿,或基于它构建新的功能.

    例外

    从始至终只花一周左右时间的一个程序员的项目或许可以不需要VCS而生存吧.

    参考

    [BetterSCM] · [Brooks95] $11, $13 · [CVS]

    4. 在代码审阅上作投入

    摘要

    代码审阅:更多双眼睛将会带来更好的质量.展示你的代码,并阅读他人的.你们都将相互学习或受益.

    讨论

    一个良好的代码审阅过程在许多方面都对你的团队有好处.它可以:
  • 有益的平等的压力可以增加代码质量.
  • 可以找到bugs、移植性不好的代码以及潜在的度量问题.
  • 通过思想的互补培养形成的设计和实现.
  • 带动新成员和初级者迅速提升能力.
  • 在团队中形成共同价值和团队意识.
  • 增加精英、信心、动机和专业自豪心.
  • 许多开发商既不对代码质量和团队质量进行奖赏,也不投入时间和金钱鼓励他们.希望我们从现在起几年都不会食言,但我们感觉到这种趋势正在慢慢改变,部分原因是由于对安全软件的需求的增长.代码审阅正有助于这种趋势,另外也是一个极好的(和免费的)内部训练方法.
    即使你的雇主还不支持代码审阅方法,你也要增加管理知识(提示:要开始,给他们看这本书)以及无论如何要尽你最大努力去安排时间并引导审阅的进行.这时间是值得花的.
    将代码审阅作为你的软件开发周期的一项常规程序.如果你和你的队友赞同基于激励(也可能是挫折)的奖惩制度,就会好得多.
    不要做得太形式化了,写一封简单的邮件就足够将代码审阅做得很好了.这会使你更容易跟踪自己的进程以及避免重复.
    当审阅他人的代码时,你可能想在旁边保留一个供参考的清单.窃以为一个好的清单可能正是你正在读的这本书的目录表.满意吧!
    摘要:我们知道我们在给"唱诗班"布道,但是不得不说.你们的自负或自我主义也许讨厌代码审阅,但你们中的少量天才程序员喜欢它,因为它会有成效并使代码更好,使程序更强健.

    参考

    [Constantine95] $10, $22, $33 · [McConnell93] $24 · [MozillaCRFAQ]
  • posted @ 2005-11-22 13:46 可冰 阅读(4994) | 评论 (9)编辑 收藏

    2005年11月20日 #

    自从国庆期间换Linux操作系统后,就再也没有来写过日志了,但我还是经常上来看看的。
    我也不知道这是怎么回事,也不是很忙啊。在自己机子上弄了几个网页,就在上面和同学们互相交流,写一些文章;但现在也没有再弄了。
    我的激情好像总是很快的消逝。以后有过几个项目的念头,都只是刚做了个开始,花几天或一周时间后就没激情了。现在也是刚找了几个同学组织了一个小的团队来写点程序,但经常这一个月左右后,发现我好像又想换其它的学习目标了。
    我为什么总是这样子呢?
    现在心情又是周期性地落在了低谷,这一周几乎什么都没做。上课也都没兴趣。开了两门选修课XML和ASP.NET;XML了解过,但不深入,老师讲得太敷浅,想自己学,又不好跟老师说,担心说我看不起老师,但学分得要啊,不选又不行;ASP.NET也是用过的,但对它没太大兴趣,看了别人的教材,那些内容基本上都知道的,通过考试是没问题的,但还是放不下这好几个破学分。我发现我真是给现在的教育套住了。
    得下个决心了!……好像我下的决心也不少啊,但也基本上都没能坚持几天,唉……!
    这样的生活何时是个头啊……
    posted @ 2005-11-20 15:00 可冰 阅读(352) | 评论 (1)编辑 收藏

    2005年10月7日 #

    忽然发现自己这大学几年都是在没有任何的目标的生活着,没有一点激情,有时候想着真是有点颓废啊.想当初为高考拼搏时是多么的有劲啊,能在那么长的时间里一直不放松.虽然大学生活已经接近尾声了,但还不算太晚,花点时间好好给自己确定一个目标吧!

    posted @ 2005-10-07 14:25 可冰 阅读(270) | 评论 (0)编辑 收藏

    2005年9月29日 #

    上周,我花了很多心思使用模板写了一个UTF-8与UNICODE相互转换的功能(见文件code.rar),刚开始感觉还可以,但这几天慢慢的觉得,为什么不直接提供两个函数呢,这样不是简单方便吗?我这样的设计又能带来额外的什么好处呢?刚开始我是想提供比较方便好用以及容易扩展与维护的代码,但现在感觉到与直接提供C式的函数并没有多少额外的好处.或许这样的简单功能根本就用不着这样复杂的代码吧.正如Eric Raymond对C++的评价一样,它"使程序员倾向于写复杂的代码".
    我想大家看看我的代码,给我一点意见和建议.
    posted @ 2005-09-29 20:34 可冰 阅读(8971) | 评论 (10)编辑 收藏

    仅列出标题  下一页