C++变量和基本类型详解

目录

  • 基本内置类型
  • 1. 不同平台下基本类型的字节数
  • 2. 算数类型的最小尺寸
  • 3. 数据类型选择的经验准则
  • 4. 有符号类型和无符号类型
  • 5.初始化与赋值
  • 6. 声明与定义
  • 7. C++关键字
    • 8.1 初始化
    • 8.2 const引用
    • 8.3 const与指针
      • 小结:
    • 9. constexpr 和常量表达式
      • 10. 处理类型
      • 总结

        基本内置类型 算术类型分为两类:整型(包括字符和布尔类型在内)和浮点型

        1. 不同平台下基本类型的字节数
        类型 16位平台 32位平台 64位平台
        char 1 1 1
        short 2 2 2
        int 2 4 4
        long 4 4 8
        long long / 8 8
        指针 2 4 8
        float 4 4 4
        double 8 8 8
        数据类型long long 是在C++11中新定义的。

        2. 算数类型的最小尺寸 算术类型分为两类:整型(包括字符和布尔类型在内)和浮点型
        类型 含义 最小尺寸
        bool 布尔类型 未定义
        char 字符 8位
        wchar_t 宽字符 16位
        char16_t Unicode字符 16位
        char32_t Unicode字符 32位
        short 短整型 16位
        int 整型 16位
        long 长整型 32位
        long long 长整型 64位
        float 单精度浮点数 6位有效数字
        double 双精度浮点数 10位有效数字
        long double 扩展双精度浮点数 10位有效数字

        3. 数据类型选择的经验准则
        • 当知晓数值不可能为负时,选用无符号类型
        • 使用int执行整数运算,short常常太小,long和int一般尺寸一样。如果int不够,用long long。
        • 在算数表达式中不要使用char或bool,使用char特别容易出问题。如果要使用一个不大的整数,那么明确执行为signed char或unsigned char。
        • 执行浮点数运算用double,float通常进度不够而且两者计算代价相差无几。Long double一般没有必要,且消耗不容忽视。

        4. 有符号类型和无符号类型
        • 无符号类型赋值超出其范围,结果是取模后的值。如unsigned char c = -1; //假设char占8bit,c的值为255
        • 有符号类型赋值超出其范围,结果未定义。如signed char c2 = 256; //假设char占8bit,c2的值未定义
        • 切勿混用带符号类型和无符号类型。
        • 算数表达式中既有无符号数又有带符号数,带符号的数会转换成无符号的数

        5.初始化与赋值 初始化和赋值是两个完全不同的操作。
        • 定义于任何函数体外的之外的变量被初始化成0
        • 定义于函数体(块作用域)内的内置类型的对象如果没有初始化,则其值未定义。养成初始化内置变量的习惯。
        • 类的对象如果没有显式地初始化,则其值由类确定。

        6. 声明与定义
        • 声明使得一个名字为程序所知,定义会申请存储空间,还可能为其赋初始值
        • (分离式编译) 如果想声明一个变量而非定义它,就在变量名前添加关键字extern,而且不要显式地初始化变量
        • 对于复杂的声明语句,可以从变量名从右往左理解
        • 变量能且只能被定义一次,但是可以被多次声明

        7. C++关键字 8. const
        8.1 初始化
        默认状态下,const对象仅在文件内有效。
        在编译的过程中,编译器会把所有用到该const变量的地方都替换成相应的值。所以编译器必须知道变量的初始值,如果存在多个文件的情况下,每个文件必须知道const的初始值(const对象也必须初始化)。但由于默认状态下,const对象仅在文件内有效,当多个文件同时出现同名的const变量时,其实就相当于分别定义了不同的变量。
        如果想只定义一次怎么做呢?
        只需要无论是声明还是定义都标记extern关键字即可。
        //file1.cppextern const i=1; //file2.cppextern const i;

        如果想要在多个文件之间共享const 对象,必须在变量之前添加extern关键字

        8.2 const引用
        定义:把引用绑定到const对象上,即为对常量的引用(reference to const)。
        引用类型必须与其所引用对象类型一致(但是有两个例外),
        8.2.1 与普通引用不同的是不能让非常量引用指向一个常量变量。
        int i= 0; const int &ci = i; int &ri = ci;

        C++变量和基本类型详解
        文章图片


        因为非常量引用可以修改它所绑定的对象,但是常量引用不能,如果非常量引用指向一个常量变量合理的话,那么非常量引用可以修改它所绑定的对象的值,这显然是不正确的。
        8.2.2 初始化常量引用时允许将以任意表达式作为初始值,只要表达式的结果能转换成对应类型即可。
        8.2.2.1允许常量引用绑定分常量的对象、字面值,甚至一个一般表达式
        double dval = 3.14; const int &ri = dval; std::cout<<"dval:"< 编译器会将上面代码变成:
        const int temp= dval; const int &ri = temp; std::cout<<"dval:"< 在这种情况下面,ri绑定了一个临时量
        ri不是常量引用的时候会发生错误:
        double dval = 3.14; int &ri = dval; // error: invalid initialization of non-const reference of type ‘int&' from an rvalue of type ‘int'std::cout<<"dval:"< 编译器会将上面代码变成:
        int temp= dval; int &ri = temp; std::cout<<"dval:"< 由于临时值的特殊性,程序员并不能操作临时值,而且临时值随时可能被释放掉,所以,一般说来,修改一个临时值是毫无意义的,据此,c++编译器加入了临时值不能作为非const引用的这个语义限制。
        8.2.2.2 const引用可能用一个非const对象
        int i =0; int &ri = i; const int &ci = i; ci = 2; // error: assignment of read-only reference ‘ci'

        常量引用仅对引用可参与的操作做出限定,对于引用的对象本身是不是一个长量未作限定

        8.3 const与指针
        指针的类型必须与其所指对象的类型一致(但是有两个例外)
        允许一个指向常量的指针指向一个非常量对象.
        和const引用差不多,指针常量的指针也没有规定所指的对象必须是一个常量
        8.3.1 指向常量的指针和常量指针
        指向常量的指针(指针可以改变,指针的值不可变):
        const int x=1; const int *p = &x; //p为指向常量x的指针int *p = &x; //错误,因为p只是个普通指针

        常量指针(不变的指针而不是指针指向的值):
        int x=0; int *const p = &x; //p为常量指针(允许一个指向常量的指针指向一个非常量对象.)const int xx=0; const int *const pp= &xx; //pp为指向常量的常量指针(

        int x=0; int y = 11; const int *p = &x; //p为常量指针(允许一个指向常量的指针指向一个非常量对象.)int*const cp = &x; const int *const pp= &x; //pp为指向常量的常量指针x = 1; std::cout<<"x:"<
        小结:

        常量指针,指针本身是一个常量,不可以改变指向的对象,但是可以改变指向对象的值,可以使用解引符改变地址所指向的值
        指向常量的指针,可以重新指定指向新的对象,但是不可以改变对象的值.
        int errNumb =0; int *const curErr = &errNumb; // curerr 将一直指向errNumb errNumb 的值变化了curerr的值也跟着变化const double pi = 3.14159; const double *const pip = π // pip 是一个指向常量对象的常量指针std::cout<<"curErr:"<<*curErr<
        输出:

        curErr:0

        pip:3.14159
        8.3.2 顶层const和底层const
        【C++变量和基本类型详解】指针如果添加const修饰符时有两种情况:
        顶层const:表示指针本身是一个常量
        底层const:表示指针所指向的对象是一个常量

        9. constexpr 和常量表达式
        常量表达式(const experssion):是指
        1.值不会改变 并且
        2.在编译过程就能得到计算结果的表达式。
        字面量属于常量表达式,用常量表达式初始化的const对象也是常量表达式。
        9. 1 constexpr 变量:

        一般来说,如果 你认定变量是一个常量表达式,那就把它声明成constexpr类型函数:

        constexpr函数是指能用于常量表达式的函数。

        应遵循的约定:函数返回类型及所有形参的类型都是字面值类型,而且函数体中必须有且只有一条return 语句。

        constexpr函数体内可以有其他语句,只要这些语句在运行时不执行任何操作。(例如,空语句、类型别名和using声明等)

        constexpr函数被隐式地指定为内联函数。
        9. 2字面值类型
        常量表达式的值需要在编译时就得到计算,因此对声明constexpr时用到的类型必须有所限制。因为这些类型一般比较简单,值也显而易见、容易得到,就把它们称为“字面值类型”(literal type)。
        字面值类型范围:
        算术类型、引用和指针都属于字面值类型。某些类也是字面值类型,它们可能含有constexpr函数成员。自定义类Sales_item、IO库、string类型不属于字面值类型。
        9. 3constexpr 和指针
        尽管指针和引用可以定义成constexpr,但它们的初始值受到严格限制。一个constexpr指针的初始值必须是nullptr、0或存储于某个固定地址中的对象。
        constexpr int *q = nullprt 等价于 int const *q = nullprt
        函数体内定义的变量一般来说并非存放在固定地址中,因此constexpr指针不能指向这样的变量。定义于函数体外的对象其地址固定不变,能用来初始化constexpr指针。
        允许函数定义一类有效范围超出函数本身的变量,如局部静态变量,这类变量和定义在函数体之外的变量一样有固定地址,因此constexpr引用能绑定到这样的变量上,constexpr指针也能指向这样的变量。

        10. 处理类型
        10.1 类型别名 typeof
        typedef double a; typedef wages base,*p; //等价于 double base ,*p;

        using
        using SI = Sales_item; SI item; //等价于 Sales_item item;


        总结 本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

          推荐阅读