C++编程思想重点笔记(下)

本文探讨了C++编程中的宏的优缺点,强调了存储类型指定符的使用注意事项。接着,详细解释了位拷贝与值拷贝的区别,展示了如何通过位拷贝导致的错误。文章还讨论了如何避免调用拷贝构造函数,并解释了私有继承的目的。最后,阐述了C++中的RTTI(运行时类型识别)概念及其两种使用方法。
摘要由CSDN通过智能技术生成

上篇请看:C++编程思想重点笔记(上)

  1. 宏的好处与坏处

    • 宏的好处:#与##的使用

      三个有用的特征:字符串定义、字符串串联和标志粘贴。

      字符串定义的完成是用#指示,它容许设一个标识符并把它转化为字符串,然而字符串串联发生在当两个相邻的字符串没有分隔符时,在这种情况下字符串组合在一起。在写调试代码时,这两个特征是非常有效的。

           
           
           
      1. #define DEBUG(X) cout<<#X " = " << X << endl

      上面的这个定义可以打印任何变量的值。 
      我们也可以得到一个跟踪信息,在此信息里打印出它们执行的语句。

           
           
           
      1. #define TRACE(S) cout << #S << endl; S

      #S定义了要输出的语句。第2个S重申了语句,所以这个语句被执行。当然,这可能会产生问题,尤其是在一行for循环中。

           
           
           
      1. for (int i = 0 ; i < 100 ; i++ )
      2. TRACE(f(i)) ;

      因为在TRACE( )宏里实际上有两个语句,所以一行for循环只执行第一个。

           
           
           
      1. for (int i = 0 ; i < 100 ; i++ )
      2. cout << "f(i)" << endl;
      3. f(i); // 第二条语句脱离了for循环,因此执行不到

      解决方法是在宏中用逗号代替分号

      标志粘贴在写代码时是非常有用的,用##表示。它让我们设两个标识符并把它们粘贴在一起自动产生一个新的标识符。例如:

           
           
           
      1. #define FIELD(A) char *A##_string;int A##_size

      此时下面的代码:

           
           
           
      1. class record{
      2. FIELD(one);
      3. FIELD(two);
      4. FIELD(three);
      5. //...
      6. };

      就相当于下面的代码:

           
           
           
      1. class record{
      2. char *one_string,int one_size;
      3. char *two_string,int two_size;
      4. char *three_string,int three_size;
      5. //...
      6. };
    • 宏的不好:容易出错 
      下面举个例子即可说明:

           
           
           
      1. #define band(x) (((x)>5 && (x)<10) ? (x) :0)
      2. int main() {
      3. for(int i = 4; i < 11; i++) {
      4. int a = i;
      5. cout << "a = " << a << "\t";
      6. cout << "band(++a)" << band(++a) << "\t";
      7. cout << "a = " << a << endl;
      8. }
      9. return 0;
      10. }

      输出:

      a = 4 band(++a)0 a = 5 
      a = 5 band(++a)8 a = 8 
      a = 6 band(++a)9 a = 9 
      a = 7 band(++a)10 a = 10 
      a = 8 band(++a)0 a = 10 
      a = 9 band(++a)0 a = 11 
      a = 10 band(++a)0 a = 12

  2. 存储类型指定符 
    常用的有staticextern。 
    不常用的有两个:一是auto,人们几乎不用它,因为它告诉编译器这是一个局部变量,实际上编译器总是可以从 变量定义时的上下文中判断出这是一个局部变量。所以auto是多余的。还有一个是register,它也是局部变量,但它告诉编译器这个特殊的变量要经常用到,所以编译器应该尽可能地让它保存在寄存器中。它用于优化代码。各种编译器对这种类型的变量处理方式也不尽相同,它们有时会忽略这种存储类型的指定。一般,如果要用到这个变量的地址, register指定符通常都会被忽略。应该避免用register类型,因为编译器在优化代码方面通常比我们做得更好。

  3. 位拷贝(bitcopy)与值拷贝的区别(很重要) 
    由1个例子来说明:一个类在任何时候知道它存在多少个对象,可以通过包含一个static成员来做到,如下代码所示:

       
       
       
    1. #include <iostream>
    2. using namespace std;
    3. class test
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值