• 《c++ Primer Plus 第6版》读书笔记(1)


    因为工作需要,又要开始写c++了,但是c++发展的比较快,上学的时候虽然写过不少,但是也没有一个系统的学习。

    在换工作期间,打算重新开始系统性的学习c++。这本书是我工作之前买的,一直没有读过,用的版本应该是c++11。现在好像已经出到很后面的版本了,一些新的特性等之后再学吧。

    另外,文章主要为自己学习所用,如果内容能对看客提供些许帮助,不胜荣幸。

    目录

    本书共有18个大章节。外加一些附录内容。

    会随着目录依次记录学习。但是一些非常基础的东西我应该会略过。

    第1章 预备知识

    本章节包括:

    • c,c++发展历史与基本原理
    • 过程性编程和面向对象编程
    • c++如何在c基础上添加面向对象概念的
    • c++如何在c基础上添加泛型概念的
    • 编程语言标准
    • 创建程序技巧

    1.1 c++简介

    1.2 C++简史

    这一张主要介绍了c++的发展历史,我大块跳过了。

    1.2.3面向对象编程

    OOP(面向对象编程)强调的是数据,试图让语言来满足问题的要求。其理念是设计与问题的本质特性相对应的数据格式。OOP程序设计方式首先设计类,准确表示了程序要处理的东西。OOP还有助于代码的可重用。

    C++中,类作为一种规范,描述这种新型数据格式,对象是符合这种规范设定所创建的数据。

    1.2.4C++和泛型编程

    c++支持泛型编程编程模式。与OOP的目标相同,都是为了重用代码和简化抽象概念。

    不同点是,OOP其强调编程的数据方面,但是泛型编程强调的是独立于特定数据类型

    1.4 程序创建的技巧

    运行c++程序的具体步骤大体如下:

    1. 使用文本编辑器编辑代码,称之为源代码。
    2. 编译源代码,将源代码翻译成机器语言。
    3. 将目标代码和其他代码连接起来,连接至将目标代码同函数的目标代码与一些标准启动代码组合起来,生成程序的运行阶段版本,称之为可执行代码。

    1.4.1创建源代码文件

    C++实现源代码文件的扩展名
    UNIXC、cc、cxx、c
    GNU C++C、cc、cxx、cpp、c++
    Digital Marscpp、cxx
    Borland C++cpp
    Watcomcpp
    Microsoft Visual C++cpp、cxx、cc
    Freestyle Code Warriorcp、cpp、cc、cxx、c++

    1.5 总结

     C语言新增了诸如控制结构和函数等特性。

    C++增加了对面向对象编程和泛型编程的支持。

    ISOC++标准(C++98/03和C++11)为确保众多实现的兼容提供了基础。

    第2章 开始学习C++

    本章节包括:

    • 创建C++程序
    • C++程序的一般格式
    • #include编译指令
    • main()函数
    • cin输入
    • cout输出
    • C++注释
    • 使用endl
    • 声明和使用变量
    • 定义和使用函数

    2.1进入C++ 

    C++语法的入口由函数头int main()开始。main()被启动代码调用,启动代码是编译器加到程序内的,是程序和操作系统的桥梁。

    C语言中使用的写法是,int main(void),c++中淘汰了这种写法。这种写法等价于void main(),但是由于系统兼容性,应该尽量使用int main()的标准格式。

    ANSI/ISO C++标准对于函数进行了更改,如果在最后没有加return 0的语句,那么会隐式加入这条语句,仅限于main()。

    通常情况下,C++必须包含一个main()函数。

    但是在一些特定的场景下,比如说编写一个动态链接库模块(DDL),由于DDL不是一个完整的程序,所以是可以没main()的;专用环境的程序,比如控制器芯片,可能不用main;一些编码框架,存在隐式的main。

    2.1.2 C++注释

    C风格的注释是使用/**/,C++的风格是使用//。

    应该尽可能用C++风格的注释,避免出现问题。

    2.1.3 C++预处理器和iostream文件

    C++的预处理器会在程序进行主编译之前对文件进行处理,它处理名称以#为开头的编译指令。

    例如,使用cin和cout需要包含#include

    2.1.4 头文件名

     例如iostram这样的文件叫做包含文件,也叫头文件。

    C语言的头文件中可能会使用扩展名.h,C++中可能会去掉.h而在前缀加上c,比如math.h改成cmath。而对于纯粹的c++库,则没有,比如iostream。

    头文件类型约定示例说明
    C++旧式风格以.h结尾iostream.hC++程序可以使用
    C旧式风格以.h结尾math.hC、C++程序可以使用
    C++新式风格没有扩展名iostreamC++程序可以使用,使用namespace std
    转换后的C加上前缀ccmathC++程序可以使用,可以使用不是C的特性,如namespace std

    2.1.5 名称空间 

    名称空间是C++的一项特性,旨在编写大型程序时,能够将不同厂商的代码进行组合。

    比如说两个已经封装好的产品中都包含wanda()名称的函数,那么在调用时,编译器讲不知道所指代的版本。使用名称空间的话,能够将产品封装在一个名称空间单元中,可以直接调用。那么上面的例子中,一个厂商可以将命名空间命名为Micro,那么函数的全程就变成了Micro::wanda()。

    使用这种方法,类,函数,变量是C++编译器的基本组件,被放置在名称空间std中。

    由于多数用户不喜欢引入名称空间,所以using编译指令应运而生,使用using namespace std;可以让人们不用在语句前加std::。

    但是这实际上是一种偷懒的方式,在大型项目中容易有隐患。更好的方式是,只使所需要的名称可用:

    1. using std::cout;
    2. using std::endl;
    3. using std::cin;

    这样不必使用using namespace std便可以使用cin和cout。

    当然,如果要使用其他定义,那么还需要加入using列表。

    2.1.6 使用cout进行C++输出

    从概念上看,输出是一个流,即从程序流出的一系列字符。

    cout的对象属性包括一个插入运算符(<<),表示将右侧的数据插入到流中。

    cout << "Hello World";

    重载运算符 

    其实是将一个字符串语句插入到了输出流中。

    可能注意到,插入运算符(<<)很像左移运算符(<<)。其实这是一个运算符重载的例子。通过重载,不同的运算符将有不同的含义。

    C语言本身也有一些运算符重载的情况,比如&既表示取地址,又表示与位运算。*表示地址引用,又表示乘法。C++扩展了运算重载符的概念,允许用户为自定义类型定义新的运算方式。

    控制符endl

    endl也是在头文件iostream中定义的,位于命名空间std中。

    endl表示重启一行。诸如endl等对cout有特殊含义的特殊符号被称为控制符。

    换行符

    C++中还可使用C语言的旧版方式,使用\n。

    和endl的一个差别在于,endl确保程序继续运行前刷新输出(将其立即显示在屏幕上) ;使用“\n”不能提供这样的保证,意味着在有些系统中,有时可能在输入信息后才会出现提示。

    2.1.7 C++源代码的格式化

    C++中使用了分号来表示语句的结尾。说明可以将一条语句放置在多行上。

    源代码中的标记和空白 

    一行代码中不可分割的元素叫做标记,空格、制表符、回车统称为空白。

    C++源代码风格 

    • 每条语句占一行 
    • 每个函数有一个开始花括号和一个结束花括号,两个括号各占一行。
    • 函数中的语句都相对于花括号进行缩进。
    • 与函数相关的圆括号周围没有空白

    2.2 C++语句

    2.2.1 声明语句和变量

    C++中使用声明语句来指出存储类型并提供位置标签。

    比如int carr;提供了需要的内存和内存单元的名称。编译器来负责分配和标记内存的细节。

    C++中,所有的变量都必须声明。在一些语言,比如basic中,可以在使用变量时创建变量,但是这样可能会出现拼写错误难以调试的问题,声明变量可以发现潜在的问题。

    C++通常的做法是在使用变量之前进行声明。

    2.2.2 赋值语句

    赋值语句会将值赋值给存储单元。carr=25;其中=叫做赋值运算符。 C++中可以连续使用赋值运算符。

    1. int a;
    2. int b;
    3. int c;
    4. a=b=c=1;

    赋值将从右向左进行。

    2.2.3 cout的新花样

    cout << carr;

    首先,cout将carr替换成当前值25,然后把值转换成合适的输出字符。

    cout的智能行为源自C++的面向对象特性。C++插入运算符将根据后面数据类型相应的调整其行为。是运算符重载的一个例子。

    2.3 其他C++语句

    2.3.1 使用cin

    C++将输入看做流入程序的字符流。

    iostream文件将cin定义为一个表示这种流的对象。

    2.3.2 使用cout拼接

    cout可以一条语句输出多个值。

    2.3.3 类简介 

    类是C++中面向对象编程的核心概念之一。

    cout是一个ostram类对象,cin是一个istream类对象,也是在iostream中定义的。

    类描述了一种数据类型的全部属性(包括可使用它执行的操作),对象是根据这些描述创建的实体。

    就想函数可以来自函数库一样,类也可以来自类库。C++之所以这么流行,很大程度上就是因为存在大量支持UNIX,Mac和windows编程的类库。

    2.4 函数

    2.4.1 使用有返回值的函数

    比如C++中包含一个sqrt()的函数,可以返回平方根。

    x = sqrt(6.25)

    其中sqrt(6.25)被称为函数调用。sqrt称为被调用函数。6.25称之为参数。

    在使用函数之前,C++编译器必须知道函数的参数类型和返回值类型。C++需要为每个使用到的函数提供原型。

    比如,sqrt()的函数原型就像这样:double sqrt(double);

    原型结尾的分号表明这是一条语句,是一个原型;如果省去分号,那么编译器将把这行代码解释为一个函数头。

    不要混淆函数原型和函数定义。一般库文件中包含了函数的编译代码,而头文件中则包含了原型。

    C++库函数存储在库文件中,编译器编译程序时,必须在库文件中搜索使用的函数。自动搜索哪些库文件,因编译器而异。

    2.4.2 函数变体

    函数也可以接受多个参数,或者不接收参数。

    int rand(void); void明确指出,该函数不接受任何参数。如果省略void,括号为空,C++会将其解释为一个不接受任何参数的隐式声明。

    不需要返回值的函数,也可以使用void指定返回类型。

    2.4.3 用户定义的函数

    一般的格式为,在int main() 之前定义函数原型,在之后实现函数定义。

    int main() 的返回值不是返回给程序的其他部分,而是返回给操作系统。通常约定,返回值为0时一位置程序运行成功,否则意味着出现问题。

    因此,如果C++程序无法打开文件,可以将其设计为返回一个非零值。

    另外,C++存在专属关键字,比如return,int,void等,这些关键字是不能够作为变量名的。

    2.4.4 用户定义的有返回值的函数

    2.4.5 在多函数程序中使用using编译指令

    通常有以下几种方式能够让程序访问名称空间std:

    • 将using namespace std; 放在函数定义之前,让文件中所有的函数都能够使用名称空间std中的所有的元素。
    • 将using namespace std; 放在特定的函数定义中,让该函数都能够使用名称空间std中的所有的元素。
    • 在特定的函数中使用类似 using std::cout; 这样的编译指令,而不是using namespace std; ,让函数能够使用指定的元素。
    • 完全不使用using,而是在需要使用名称空间std元素时,使用前缀std:: 。

    2.5 总结

    C++语句的类型:

    • 声明语句
    • 赋值语句
    • 消息语句
    • 函数调用
    • 函数原型
    • 返回语句

    第3章 处理数据

     本章内容包括:

    • C++变量的命名规则
    • C++内置的整形——unsigned long, long, unsigned int, int, unsignrf short, short ,char, unsigned char ,signed char, bool
    • C++11新增的整形:unsigned long long, long long
    • 表示各种整形的系统限制的climits文件
    • 各种整形的数字字面值(常量)
    • 使用const限定符号来创建符号常量
    • C++内置的浮点类型:float, double, long double
    • 表示各种浮点类型的系统限制的cfloat文件
    • 各种浮点类型的数字字面值
    • C++的算数运算符
    • 自动类型转换
    • 强制类型转换

    3.1 简单变量 

    3.1.1 变量名 

    C++命名规则:

    • 只能使用字母字符,数字,下划线。
    • 第一个字符不能是数字
    • 区分大写和小写字符
    • 不能将C++关键字用作名称
    • 以两个下划线(__fools)或者下划线和大写字母打头(_MyStars)的名称被保留给编译器使用。
    • 以一个下划线开头的名称被保留给实现,用作全局标识符。
    • C++对于名称的长度没有限制

    如果想要使用两个或者更多的单词组成一个名称,通常情况下是使用下划线将单词分开。

    在C++所有主观风格中,一致性和精度是最重要的。

    3.1.2 整形

    C++总共有10种整数类型可供选择。

    描述存储的内存越多,整数值范围越大。

    3.1.3 整形 short , int , long , long long

    C++提供了一种灵活的标准,确保了最小长度,如下:

    • short最少16位
    • int至少和short一样长
    • long至少32位,至少和int一样长
    • long long至少64位,至少和long一样长

    当前很多系统使用了最小长度,即short为16位,long为32位,但是不同的系统下int还是有多种选择。可能在一个系统中int为16位,另一个系统中为32位。

    头文件climits中包含了关于整形限制的信息。定义了表示各种限制的符号名称,比如INT_MAX为int最大取值,CHAR_BIT为字节位数。

    sizeof运算符支出,在使用8位字节系统中,int长度为4个字节,可对类型名和变量名使用sizeof运算符。

    climits中的符号常量如下

    符号常量表示
    CHAR_BITchar的位数
    CHAR_MAXchar的最大值
    CHAR_MINchar的最小值
    SCHAR_MAXsigned char的最大值
    SCHAR_MINsigned char的最小值
    UCHAR_MAXunsigned char的最大值
    SHRT_MAXshort的最大值
    SHRT_MINshort的最小值
    USHRT_MAXunsigned short的最大值
    INT_MAXint的最大值
    INT_MIN

    int的最小值

    UNIT_MAXunsigned int的最大值
    LONG_MAXlong的最大值
    LONG_MINlong的最小值
    ULONG_MAXunsigned long的最大值
    LLONG_MAXlong long的最大值
    LLONG_MINlong long的最小值
    ULLONG_MAXunsigned long long的最大值

    climits文件中包含与下面类似的语句行:

    #define INT_MAX 32767

    其中#define和#include一样,也是预处理器编译指令。意思为将所有的INT_MAX替换为32767。修改后的程序将在完成替换之后再进行编译。

    #define是C语言遗留下来的,C++可以使用const来创建符号常量。所以不会经常用#define

    然而被设计成用于C和C++的头文件中,必须使用#define。

    对变量初始化的方式:

    使用字面值或者其他常量来赋值:

    int a=b;

    int a=14;

    如果不赋值,可能会产生未知错误。

    C++11中使用{}对变量进行赋值。

    int emus{12};

    int emus = {12};

    int emous = {}; // 大括号为空表示0值

    使用这种方法可以防范类型转换错误。通过使用C++的大括号初始化,可作用于任何类型。是一种通用的初始化语法。

    3.1.4 无符号类型

    可以使用unsigned关键字进行声明,表示无符号。

    3.1.5 选择整数类型

    通常情况下使用int。

    当有大型整数数组时,使用short有必要。

    16位系统转到32微系统,int数组内存量会翻倍,但是short数组不受影响。

    3.1.6 整形字面值

    如果数字第一位为1-9,那么就是十进制。

    如果数字第一位为0,第二位为1-7,那么就是八进制。

    如果数字前两位为0x或0X,那么就是十六进制。

    cout默认情况下是十进制输出的。(无论什么方式,在计算机中都是二进制数。)cout还提供了dec, hex , oct控制符,用于指示cout的输出格式。

    1. using namespace std;
    2. int a = 42;
    3. // 10进制
    4. cout << a<< endl;
    5. // 16进制
    6. cout << hex;
    7. cout << a<< endl;
    8. // 8进制
    9. cout << oct;
    10. cout << a << endl;

    3.1.7 C++如何确定常量类型

    C++编译器除非有理由,否则数字都存储为int。(除非存不下,或者有特殊后缀指定)。

    后缀为L表示为long常量。

    后缀U表示为unsigned int常量。

    后缀为LL表示为long long常量。

     

    3.1.8 char类型:字符和小整数

     在美国最常用ASCII字符集。

    C++支持的宽字符可以存储更多值。比如Unicode。

    可以用cout.put(ch); 显示一个字符。意思为通过类对象cout使用函数put()。

    对于特殊的字符,C++提供了转义序列。

    Unicode提供了一种表示各种字符集的解决方案——为大量字符和符号提供标准数值编码,ASCII是Unicode的子集。

    与int不同,char既不是没有符号也不是有符号,取决于编译器。如果想做微数值类型使用,那么unsigned char和signed char的范围是有差距的。0-255 和-128-127。

    C++11中新增了char16_t和char32_t,均为无符号。

    C++使用前缀u表示char16_t字符常量和字符串常量,比如u"C"和u"be good"。

    C++使用前缀U表示char32_t字符常量和字符串常量,比如U"C"和U"be good"。

    类型char16_t和/u00F6形式的通用字符名匹配。

    类型char32_t和/U0000222B形式的通用字符名匹配。

    3.1.9 bool 类型

    非零值转为true;零值转为false.

    3.2 const限定符

    使用const修饰的变量被初始化后,编译器不允许再修改值。

    一种常见的方法是将名称首字母大写,表示为常量。另一种约定是将整个名称大写。

    const之所以比#define好,首先,能够明确指定类型,其次,可以使用C++的作用域规则限制在特定函数或者文件;第三,可以用于更加复杂的类型。

    3.3 浮点数

    浮点数可以表示小数部分。

    计算机会对浮点数进行两部分存储,一部分表示值,另一部分表示对值放大或者缩小。

    比如,34.1245和34124.5。第一个数表示为0.341245(基准值)和100(缩放因子);第二个数表示为 0.341245(基准值一样)和10000(缩放因子更大)。

    缩放因子是2的幂,不是10的幂。

    3.3.1 书写浮点数

    一种方法是使用常见的书写方式,比如1.56 , 0.13 , 8.0。

    第二种是使用E或者e,比如2.5e+8 , 7e5 , 9.11e -32。

    称为浮点数,就是因为小数点是可以移动的。

    3.3.2 浮点类型

    三种:float ,double , long double。

    是按照可以表示的有小数位和允许的指数最小范围来描述的。

    有效位是数字中有意义的位。

    C++对于有效位数的要求为:float至少32位,double至少48位,long double至少和double一样。但是三种类型的有效位数可以一样多。

    通常情况下,float为32位,double为64位,long double为 80/96/128位。

     这三种类型的指数范围至少为-37到37.

    在cfloat中可以找到系统的限制。

    使用cout.setf(ios_base::fixed, iosbase::floatfield); 可以迫使输出使用定点表示方法,防止使用E表示法,并将程序显示到小数点后6位。ios_base::fixed, iosbase::floatfield为iostream中的常量。

    3.3.3 浮点数常量

    通常情况下,浮点数会被保存为double,如果想保存为float,需要在后面加f/F后缀。

    对于long double 可以使用L/l后缀。

    1.234f

    2.45E20F

    20.2L

    3.3.4 浮点数的优缺点

    浮点数的优点在于表示的范围更宽。

    缺点在于精度低,而且运算速度没有整数快。

    3.4 算数运算符

    C++提供了+ - * / %五种基本运算符。

    3.4.4 类型转换

    C++自动执行很多类型转换:

    • 将算数类型的值赋给另一种算数类型的变量时
    • 表达式中包含不同的类型时
    • 将参数传递给函数时

    在进行类型转换时,通常会将一个值赋给取值范围更大的类型。

    但是将大值赋值给一个更小的类型时,可能会出现精度不够,超出范围等问题。

    C++11的校验表:

    • 一个操作树为long double,将另一个操作数转为long double
    • 否则,一个操作数为double,将另一个操作数转为double
    • 否则,一个操作数为float,将另一个操作数转为float
    • 否则,说明操作数都是整形,执行整形提升
    • 若都为有符号或者都为无符号,转换为高级别整数
    • 若一个有符号一个无符号,且无符号操作数级别比较高,那么需要转换为无符号操作数类型
    • 否则,如果有符号类型可表示为无符号类型的所有可能取值,将无符号操作数转换为有符号操作数类型
    • 否则,将两个操作数都转为有符号类型的无符号版本

    简单说就是:

    long long > long > int > short > signed char > bool

    C++可以使用int(a)或者static_cast(a)来进行类型的强制转换。

    3.4.5 C++11的auto声明

    auto可以让编译器根据初始值类型推断变量类型。

    在处理复杂类型,比如stl库中的类型时,会很好用。

    3.5 总结

    C++的数值类型,整数,浮点数,操作符,类型转换。

  • 相关阅读:
    Mac 环境下 Java JDK 的安装与环境变量配置详解(已完美解决)
    0001__非对称加密与 RSA 算法
    IntelliJ IDEA 下载安装及配置使用教程
    Java并发-交替打印的四种方法。
    element picker 时间控件,指定区间和指定月份置灰
    对比分析小游戏引擎孰优孰劣
    ros develop 相关
    友宝在线在港交所上市申请“失效”:连续两年亏损,王滨为大股东
    OpenGL ES EGL eglGetDisplay
    【PE806】Nim on Towers of Hanoi(汉诺塔游戏,生成函数)
  • 原文地址:https://blog.csdn.net/qq_35423190/article/details/126540502