TCPL学习笔记

        近来在看Bjarne Stroustrup的TCPL(The C++ Programming Language)中文特别版。看到第6章6.2.5的“增量和减量”的一节,其中举的例子,让人非常深刻地领略到C++的优雅、简洁与高效(从这个例子来看是不是高效,有待验证),下面来看看书中的例子:

         运算符 ++ 和 -- 对于在循环里增加或减少变量特别有用。例如,以0结尾的字符串可以通过下面方式复制:
        void cpy(char* p, const char* q)
       {
                while(*P++ = *q++);
       }

和C一样,C++也因为允许这类紧凑的面向表达式的编码方式而受到喜爱或者仇恨。因为
   
       while(*p++=*q++);

对于非C程序员而言是个小障碍,也因为以这种风格编写的代码在C和C++里绝非罕见,因此需要进一步仔细考察。
       首先考虑一下更传统的复制一个字符数组的方式
      
       int length = strlen(q);
       for(int i = 0; i <= length; i++) p[i] = q[i];

这确实很浪费。要确定以0结尾的字符串的长度,就需要通过读这个串去找到结尾的0。这样我们实际上就读了字符串两次:一次为确定长度,另一次是复制。试试另一种方式:

       int i;
       for(i = 0; q[i] != 0; i++) p[i] = q[i];
       p[i] = 0;      // 以0结束

用做下标的变量i可以去掉,因为p和q本身就是指针:

       while(*q != 0)
       {
              *p = *q;
                p++;            //  指向下一个字符
                q++;            //  指向下一个字符
       }
       *p = 0;                //  以0结束

后增量运算使我们可以先用变量的值,而后再增加它。我们可以将循环重新写出:

       while(*q != 0)
       {
                *p++ = *q++;
       }
       *p = 0;      //  以0结束

由于 *p++ = *q++ 的值也就是 *q,所以我们可以将这个例子重写为:

       while((*p++ = *q++) != 0) { }

在这个情况中,我们只有把 *q 复制到 *p并增加了p之后,才会注意到它的值是不是0。因此我们就可以删除设置结束0的最后一个语句。最后,我们可以看到并不需要空的块,而且 "!= 0" 也是多余的,因为指针的结束或者整数条件实际上都要与0做比较。这样,我们就得到了开始时想找的版本:

       while(*p++ = *q++);

这个版本比前面的版本更难读吗?对有经验的C或C++程序员而言并不是这样。在时间和空间上这个版本比前面的版本更有效吗?除了第一个调用strlen( )的版本外也都不一定。哪个版本最有效,也可能依机器的结构和编译的不同而不同。
       要在你的特殊计算机上复制以0结尾的字符串,最有效的方式应该是用标准的串复制函数

       char* strcpy(char* , const char* );         //   来自<string.h>

对于更一般的复制,可以使用标准copy算法。只要通用,都应该优先选用标准库的功能,而不是自己去拨弄指针和字节。标准库函数可能被在线化(inline),甚至采用特殊的机器指令实现。所以,在相信一段手工打造的代码的性能优于库函数之前,你应该先经过认真的实测。


        B.S.对这个例子的分解讲的很详细,还做了不少关于性能方面的分析和建议,非常有用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值