C++复习 02 变量和基本类型




声明,所有的朋友,如果要转我的帖子,务必注明"作者:黑啤 来源:CSDN博客"和具体的网络地址http://blog.csdn.net/nx500/archive/2007/10/21/1836075.aspx,并且我的所有博客内容,禁止任何形式的商业用途,请大家尊重我的劳动.谢谢!

目 录

二.变量和基本类型.
  001 bool/char/wchar_t/short/int/long/float/double/long double.
  002 signed/unsigned.
  003 如果把-1赋给8位的unsigned char,那么结果就是255,因为255就是-1对256求模后的值(补码).
       //  以下这段原码/反码/补码的说明摘录自muxiaodan的博客
      原码:原码就是这个数本身的二进制形式.
        例如
          
0000001  就是 + 1
          
1000001  就是 - 1
      反码:正数的反码与原码相同.负数的反码是将其原码除符号位之外的各位求反.
        [
- 3 ]反 = [ 10000011 ]反 = 11111100
      补码:正数的补码与原码相同.负数的补码是将其原码除符号位之外的各位求反之后在末位再加1.
        [
- 3 ]补 = [ 10000011 ]补 = 11111101
        特别注意,如果
+ 1之后有进位的,要一直往前进位,包括符号位 !   1000   0000   =   - 128
      为什么要设立补码呢
?
        第一是为了能让计算机执行减法.
          [a
- b]补 = a补 + - b)补
        第二个原因是为了统一正0和负0.
          正零: 
00000000
          负零: 
10000000
          这两个数其实都是0,但他们的原码却有不同的表示.但是他们的补码是一样的,都是00000000.
      
//   http://hi.baidu.com/muxiaoduan/blog/item/0b8e7d2e1239c8534fc22600.html
  004 decimal/octal/hexadecimal  16/020/0x10.
  005 unsigned/long 128u/22L/33uL.
  006 浮点数/单精度/扩展精度 3.14f/3.141593f/3.1415926L.
  007 '/0' NULL character/空字符(定义在cstdlib中).
  008 L "a wide string literal" 宽字符字面值是一串常量宽字符,同样以一个"宽"空字符结束.
  009 lvalue/rvalue (发音:ell-value/are-value) 能出现在赋值语句左边的/只能出现在赋值语句右边的.
  010 对象:就是内存中具有类型的区域.
  011 标识符:由数字/字母/下划线组成,不能以数字开头,且大小写敏感.
      不能包含两个连续的下划线,也不能以下划线开头紧跟一个大写字母.函数外定义的标识符"不能"以下划线开头.
  012 类型决定了分配给变量的存储空间的大小和可以在其上执行的操作.
  013 复制初始化/copy-initialization: int ival = 1024;
  014 直接初始化/direc-initialization: int ival(1024); 直接初始化语法更灵活,效率更高.
  015 初始化不是赋值,初始化是创建变量是赋给的初始值,赋值是擦除当前值并赋给新的值
  016 内置类型变量是否自动初始化取决于变量定义的位置.在函数体外定义的变量都初始化成0,在函数体里定义的内置类型不进行自动初始化.
  017 如果定义某个类的对象时,没有提供初始化式,这个类也可以定义初始化时的操作.它是通过定义一个默认的构造函数来实现的.
        std::string emp; //emp is an empty string;
  018 变量的定义:用于为变量分配存储空间,可以指定初始值,同一个变量在一个程序中有且仅有一个定义.
  019 变量的声明:用于向程序标明变量的类型和名字,通过extern关键字声明变量而不定义它.如果声明有初始化,那么它可以被当做是定义.
      只有当extern声明位于函数外部,可以初始化.
        extern double pi = 3.14159;
  020 用来区分名字的不同意义的上下文称为作用域.全局作用域/局部作用域/语句作用域/类作用域/命名空间作用域.
  021 const限定符.
      常量在定义后不能被修改,所以" 必须"在定义时赋值.
        const std::string hi = "hello heipi";
        const int i = 0;
      在全局作用域声明的const对象是定义该对象文件的局部变量.可以通过指定该变量为extern使之成为全局变量.
        extern const int buffSize = 1024;
  022 引用:就是对象的另一个名字.在实际程序中,引用主要用做函数的形式参数.
      不能定义引用类型的引用.
      引用必须用与该引用同类型的对象初始化.
        int ival = 1024;
        int &refval = ival; // ok
        int &refva2;        // error, 没有初始化
        int &refva3 = 0;    // error, 必须用一个对象初始化
      不能将一个引用绑定到另一个对象上.初始化是指明引用指向那个对象的唯一方法.
      const引用是指向const对象的引用.
        const int ival = 1024;
        const int &refval = ival;// ok
        int &ref2 = ival;        // error 不能将非常量引用指向一个常量类型
      非const引用只能绑定到与该引用同类型的对象." "const引用可以绑定到不同但相关的类型的对象或绑定到右值.
        int i = 0;
        const int &r1 = 42;      // ok
        const int &r2 = r1 + i;  // ok
        double dval = 3.14;
        const int &rd = dval;    // rd == 3
  023 typedef可以用来定义类型的同义词.
        1.隐藏特定类型的实现,强调类型的目的.
        2.简化复杂类型定义,容易理解.
        3.允许一个类型用于多个目的.
          typedef double wages;
          typedef double salary;
  024 枚举enum,第一个枚举成员赋值为0,可以通过中间赋值而修改枚举元素的值.
        enum color {red, blue, white=1, black}; // red:0 blue:1 white:1 blacl:2.
        color cl = blue;
  025 定义类:class开始,分号结束.
        class Sales_item {
        public:
           // ...
        private:
          std::string isbn;
          unsigned units_sold;
          double revenue;
        }; // 注意结尾的分号
      类的数据成员是在构造函数里初始化的.
      使用class定义类,第一个访问标号前的任何成员隐式的指定为private,而用struct定义类默认为public.
  026 头文件一般包含:1.类的定义;2.exteren变量的声明;3.函数的声明.
      好处:1.保证所有的文件使用给定实体的同一声明;2.当声明需要修改时,只有头文件需要修改.
      因为头文件被多个源文件包含,所以不应该包含变量或函数定义.例外:头文件可以定义类/值在编译时就已经知道的const对像和inline函数.
  027 避免头文件的多重包含
        #ifndef SALESITEM_H
        #define SALESITEM_H
        ...
        #endif
// 以下的总结来自于CSDN社区"C/C++/新手乐园"的不接不舒服斯基帖子
// http://topic.csdn.net/u/20070922/23/f2aaf4a5-7960-4cda-84a3-fa1de28f003d.html
C++中const总结
一:对于基本声明
      1.const   int   r=100;  
      //标准const变量声明加初始化,因为默认内部连接所以必须被初始化,其作用域为此文件,编译器经过类型检查后直接用100在编译时替换.
      2.extend   const   int   r=100;  
      //将const改为外部连接,作用于扩大至全局,编译时会分配内存,并且可以不进行初始化,仅仅作为声明,编译器认为在程序其他地方进行了定义.
      3.const   int   r[]={1,2,3,4};
      struct   S   {int   a,b;};
      const   S   s[]={(1,2),(3.4)};
      //以上两种都是常量集合,编译器会为其分配内存,所以不能在编译期间使用其中的值,例如:int   temp[r[2]];这样的编译器会报告不能找到常量表达式
二:对于指针
      1.const   int   *r=&x;  
      //声明r为一个指向常量的x的指针,r指向的对象不能被修改,但他可以指向任何地址的常量.
      2.int   const   *r=&x;//与用法1完全等价,没有任何区别。
      3.int   *   const   r=&x;  
      //声明r为一个常量指针,他指向x,r这个指针的指向不能被修改,但他指向的地址的内容可以修改.
      4.const   int   *   const   r=&x;  
      //综合1,3用法,r是一个指向常量的常量型指针.
三:对于类型检查
      可以把一个非const对象赋给一个指向const的指针,因为有时候我们不想从这个指针来修改其对象的值,但是不可以把一个const对象赋值给一个非 const指针,因为这样可能会通过这个指针改变指向对象的值,但也存在使这种操作通过的合法化写法,使用类型强制转换可以通过指针改变const对象:
      const   int   r=100;
      int   *ptr=const_cast <int* >(&r);//C++标准,C语言使用:int*   ptr   =(int*)&r;
四:对于字符数组
      如char   *   name   =   "china";  
      这样的语句,在编译时是能够通过的,但是"china"是常量字符数组,任何想修改他的操作也能通过编译但会引起运行时错误,如果我们想修改字符数组的话就要使用char   name[]="china";这种形式.
五:对于函数
      1.void   Fuction1(const   int   r);
      //此处为参数传递const值,意义是变量初值不能被函数改变
      2.const   int   Fuction1(int);  
      //此处返回const值,意思指返回的原函数里的变量的初值不能被修改,但是函数按值返回的这个变量被制成副本,能不能被修改就没有了意义,它可以被赋 给任何的const或非const类型变量,完全不需要加上这个const关键字.但这只对于内部类型而言(因为内部类型返回的肯定是一个值,而不会返回 一个变量,不会作为左值使用),对于用户自定义类型,返回值是常量是非常重要的,见下面条款3
      3.Class   CX;   //内部有构造函数,声明如CX(int   r   =0)
      CX   Fuction1   ()   {   return   CX();   }
      const   CX   Fuction2   ()   {   return   CX();   }
      如有上面的自定义类CX,和函数Fuction1()和Fuction2(),我们进行如下操作时:
      Fuction1()=CX(1);   //没有问题,可以作为左值调用
      Fuction2()=CX(1);   //编译错误,const返回值禁止作为左值调用.因为左值
                            把返回值作为变量会修改其返回值,const声明禁止这种修改.
      4.函数中指针的const传递和返回
      int   F1   (const   char   *   pstr);  
      //作为传递的时候使用const修饰可以保证不会通过这个指针来修改传递参数的初值,这里在函数内部任何修改*pstr的企图都会引起编译错误.
      const   char*   F2();  
      //意义是函数返回的指针指向的对象是一个const对象,它必须赋给一个同样是指向const对象的指针.
      const   char*   const   F3();  
      //比上面多了一个const,这个const的意义只是在他被用作左值时有效,它表明这个指针除了指向const对象外,它本身也不能被修改,所以就不能当作左值来处理.
      5.函数中引用的const传递
      void   F1   (const   X&   px);  
      //这样的一个const引用传递和最普通的函数按值传递的效果是一模一样的,他禁止对引用的对象的一切修改,唯一不同的是按值传递会先建立一个类对象的 副本,然后传递过去,而它直接传递地址,所以这种传递比按值传递更有效.另外只有引用的const传递可以传递一个临时对象,因为临时对象都是const 属性,且是不可见的,他短时间存在一个局部域中,所以不能使用指针,只有引用的const传递能够捕捉到这个家伙.
六:对于类
      1.首先,对于const的成员变量,只能在构造函数里使用初始化成员列表来初始化,试图在构造函数体内进行初始化const成员变量会引起编译错误.初 始化成员列表形如:X::X(int   ir):r(ir){}   //假设r是类X的const成员变量
      2.const成员函数.提到这个概念首先要谈到const对象,正象内置类型能够定义const对象一样(const   int   r=10;),用户自定义类型也可以定义const对象(const   X   px(10);),编译器要保证这个对象在其生命周期内不能够被改变.如果你定义了这样的一个const对象,那么对于这个对象的一切非const成员函 数的调用,编译器为了保证对象的const特性,都会禁止并在编译期间报错.所以如果你想让你的成员函数能够在const对象上进行操作的话,就要把这个 函数声明为const成员函数.
      假如f()是类中的成员函数的话,它的声明形如:
      int   f()const;  
      //const放在函数的最后,编译器会对这个函数进行检查,在这个函数中的任何试图改变成员变量和调用非const成员函数的操作都被视为非法
      注意:类的构造和析构函数都不能是const函数.
      3.建立了一个const成员函数,但仍然想用这个函数改变对象内部的数据.这样的一个要求也会经常遇到,尤其是在一个苛刻的面试考官那里.首先我们要弄 清楚考官的要求,因为有两种方法可以实现,如果要求不改变原来类的任何东西,只让你从当前这个const成员函数入手,那么你只有使用前面提到的类型强制 转换方法.实例如下:
      //假如有一个叫做X的类,它有一个int成员变量r,我们需要通过一个const成员函
      数f()来对这个r进行++r操作,代码如下:
      void   X::f()const
      {const_cast <X* >(this)- >++r;   }   //通过this指针进行类型强制转换实现
      另外一种方法就是使用关键字:mutable.
      如果你的成员变量在定义时是这个样子的:mutable   int   r;
      那么它就告诉编译器这个成员变量可以通过const成员函数改变.编译器就不会再理会对他的检查了 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值