• 【读书笔记】C++ primer 5th 从入门到自闭(一)


    这几天看了C++ primer 5th的一二章,有很多收获,但是有的地方因为翻译的问题也搞得理解起来颇为难受啊啊啊啊。尤其是const限定符,在C语言并没有这么多复杂的语法,在C++里面语法细节就多的不行。
    顺便做了两张思维导图

    思维导图


    细节补充

    第一章

    这一章没什么好说的,主要介绍了顺序选择循环三种基本语句,输入输出流的概念,注释,ADT(抽象数据类型)的概念初识和类的简单介绍。
    由于有C语言的数据结构的基础,所以除了C++自带输入输出流似乎也没什么可说的。

    1.iostream

    标准输入输出流库,包含两个基础类型istream和ostream。
    为了方便初学时的学习,我们使用其中的cin以及cout,前者从键盘中读取数据,后者把数据写进屏幕显示。

    2.两个输入输出运算符

    运算符>>为输入运算符,接收一个istream读入数据;
    运算符<<为输出运算符,在标准输出上打印消息。
    另外还有一个操纵符std::endl,作用为结束当前行,并将与设备关联的缓冲区中的内容刷到设备中。

    第二章

    本章主要介绍了C++中的类型与变量,大体框架已在上图列出,下面把一些细节和我认为比较重要的点(C语言中出现的特性将一般不列出)列出

    1.关于如何选择C++中的变量类型

    ①:当明确知晓数值不能为负时,用unsigned;
    ②:使用int执行整数运算。在实际运用中,short常常显得太小而long一般和int有一样的尺寸。如果你的数值超过了int的表示范围,选用long long。
    ③:在算术表达式中不要使用char或者bool,只有在存放字符或布尔值是才使用它们。因为char在一些机器上是有符号的,而在另一些机器上又是无符号的。
    ④:执行浮点数运算选用double,这是因为float通常精度不够而且双精度浮点数和单精度浮点数的计算代价相差无几。事实上,对于某些机器来说双精度运算甚至比单精度还快。long double 提供的精度在一班情况下是没有必要的,而且计算效率极低。
    ⑤:不要赋给符号类型一个超出范围的值,这样可能会导致程序崩溃或者产生非预期的值。
    ⑥:切勿混用带符号类型和无符号类型。

    2.关于十进制字面值常量

    尽管整型字面值可以存储在带符号数据类型中,但严格来说,十进制字面值不会是负数(八进制和十六进制可以)。如果我们使用了一个形如-42的负十进制字面值,那个负号并不在字面值之内,它的作用仅仅是对字面值取负值而已。

    3.关于初始化

    初始化与赋值不同

    int a=1;//初始化
    a=2;//赋值
    在C++语言中,初始化和赋值是两个完全不同的操作,初始化不是赋值,初始化的含义是创建变量是赋予其一个初始值,而复制的含义是把对象的当前值擦除,而以一个新值代替。

    列表初始化

    C++语言相对C语言对了几种不同的初始化方式:

    int a=0;//C/C++通用  
    int a={0};//列表初始化  
    int a{0};//列表初始化  
    int a(0);//C++新的初始化方式  

    用花括号初始化的方式我们称为列表初始化。现在无论是初始化还是赋值都可以用花括号了。
    当用于内置类型的变量时,这种初始化形式有一个重要特点:如果我们使用列表初始化且初始值存在丢失信息的风险,则编译器将报错:

    long double ld=3.1415926;  
    int a{ld},b={ld};  //错误:ld是浮点型,转化成整型时丢失了信息。列表初始化时编译器报错  
    int c(ld),d=ld;    //正确:虽然还是丢失了信息,但并非列表初始化,编译器不会报错;

    引用

    引用并非对象,相反的,它只是为一个以及存在的对象所起的另外一个名字,即别名。
    引用必须初始化,因为引用本身并没有内存空间,且绑定的值必须要是一个与自己声明时类型相同的对象,而非字面值。
    引用一般用于需要该变形参实际值的函数中。

    关于复合类型的声明

    定义多个变量

    经常有一种观点会误以为,在定义语句中。类型修饰符(*或者&)作用域本次定义的全部变量。造成这个观点的原因有很多,其中之一是我们可以把空格写在类型修饰符和变量名中间:

    int* p;//合法但是容易产生误导

    我们说这种写法可能产生误导是因为int*放在一起好像是这条语句中所有变量共同的类型一样。其实恰恰相反,基本数据类型是int,而不是int*。*仅仅修饰了p,而已,对该声明中的其他变量,它并不参赛任何作用:

    int *p1,p2;//p1是指向int的指针,p2是int型变量。  

    指向指针的引用

    引用本身不是一个对象,因此不能定义指向引用的指针。但是指针是对象,所以可以定义指针的引用。

    int *&p;

    如上的多重复合类型定义,要理解p到底是什么,最简单的方法是从右向左阅读p的定义。离变量名最近的符号对变量的类型由最直接的影响。

    关于const运算符

    初始化和定义

    const常量定义时必须初始化,且初始化后值不能改变。

    extern与const

    默认状态下,const对象仅在文件内有效,如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字。

    const与引用

    可以把引用绑在const对象上,就像绑定到其他对象一样,我们称之为对常量的引用。与普通引用不同的是,对常量的引用不能修改它所指的对象。
    初始化对const的引用可以使用字面值,这是引用的一个例外。

    顶层const与底层const

    顶层const表示指针本身是个常量,底层const表示指针所指的对象是一个常量。
    由于引用没有实体,永远指向另一个对象,所以对它的const一定是底层const。
    当执行对象的拷贝时,常量是顶层const还是底层const区别明显,顶层const的属性会被忽略。
    如果同时底层const,非常量可以拷贝给常量,反之不可以,因为如果把常量拷贝给非常量,非常量并不能改变所指对象的值,那么这么做是没有意义的。

    constexpr和常量表达式

    常量表达式是指值不会改变而且在编译过程就能得到计算结果表达式。
    通常情况下我们无法分辨一个初始值是不是常量表达式,在C++11中允许将变量声明为constexpr类型以便由编译器来验证变量的值是否为一个常量表达式。
    一般来说,如果你认定变量是一个常量表达式,那就把它声明成constexpr。
    constexpr如果用来声明指针,一定是顶层const。

    关于typedef与指针常量

    typedef char *pstring;
    const pstring cstr=0;
    const char *cstr;

    用typedef类型别名声明的cstr为顶层const,而没有用的为底层const。

    auto运算符

    auto让编译器通过初始值来推算所属类型。
    auto会忽略顶层const的属性,保留底层const的属性。如果想保留就在前面再加一个const。

    decltype类型表示符

    有时会遇到这种情况:希望从表达式的类型推断出要定义的变量的类型,但不希望用它的值来初始化,于是decltype出现了。
    decltype获得表达式的类型并作为说明符。
    在decltype的表达式中如果值是一个引用,那么,该引用不再是别名,而是引用类型。
    表达式多层括号一定是引用,解引用符也是引用。

  • 相关阅读:
    【C/C++】输出文件的相对路径
    PHP AES 解密的坑
    jupyter notebook 启用扩展功能
    gitflow工作流程
    C# 采集知网
    Visual Studio 2019 自带混淆工具DotFuscator不需要去网络下载
    常用Windows控制台命令
    geotools临时打断线,重新构图(graph)
    java 图(Graph)的实现
    geoTools:ESPG (无法找到ESPG。。如何添加自己的ESPG)
  • 原文地址:https://www.cnblogs.com/z-y-k/p/11296539.html
Copyright © 2020-2023  润新知