Accelerated C++品读记(1)
前言:
起码有半年没有接触过C++了,之前打下的C++基础还算不错,现在打算读一读AC,通过这本书把之前大二学的C++知识理解一篇。在读的过程中发现这本书,确实是一本好书,这本书和其他C++的书有着一个很大的不同之处在于其是以驱动为模型来介绍C++这么课程的,不过读这本书需要你有一定的C++功底,那么你可以很块的接受并且读完,如果没有也没多大问题。第一篇品读记总结和介绍下AC 0章和1章所学到的内容。
知识:
这里不按篇幅的顺序介绍了,主要介绍自己认为重要的几个东西。
(0)类型
所谓的类型,有用心学过数据结构的因该很清楚,类型是一种数据结构和对此数据结构的操作。
(1)表达式和操作数、运算符、左结合、副作用
看下面这个表达式 std::cout<< "Hello World" << std::endl;
其中std::cout、“Hello World”、std::endl就是操作数,而 <<则是操作符,操作数是一种类型的实例化对象,如std::cout其是属于std::ostream类 型,而操作符<<在不同情况下可以代表不同的操作(即其操作结果主要取决于操作数的类型),在这里它是左结合性的,所谓的左结合性就是两个相同操作符同时出现在一个变量或则字符串直接量两旁时,优先和左边的结合,所以以上这个表达式有等价于 (std::cout<< "Hello World") << std::endl;在上面std::endl是一种特殊的类型,它是一种控制器(顾名思义是有某种控制作用,在这主要用来控制流。),<<会对特定的流执行控制器所指定的动作,同时它会返回流作为其结果。
而每一个表达式都会产生一个结果,一般而言可能还会产生一定的副作用。我们以实例来讲解,如 7 + 3这个表达式的结果就是10,但是它没有副作用。但是std::cout<< "Hello World" << std::endl;的结果是std::cout至于为什么到后面的运算符重载(因为这个重载运算符<<还是返回了一个std::ostream的对象)还会在细致的讲解,但是其副作用就是在显示设备上输出“Hello world”。这就是表达式和副作用的关系。
(2)输出缓冲区和std::cout和std::cin的模型和关系。
输出缓冲区是为提高系统的运行效率,减少写操作带来的开销,其原理是这样的,我们知道在内存中存取速度远远高于从硬盘中读取到内存在进行存取,所以其久分配了一块内存单元称之为所谓的缓冲区,用来暂时存放要输出的字符。然后将多个字符一次性的输出,而不是分多次的调用写操作一个个输出,这样就大大的提高了操作系统的效率。诚然输出缓 冲区只有在以下三种情况才会进行刷新输出。第一种是,缓冲区满了。第二种是,调用std::cin进行读入操作时,会自动把缓冲区内容刷新。因为此时缓冲区内容一般是用来提示接下 去要读入的内容。第三种情况就是强制性的通知刷新。如上面的std::endl流控制器,对它的写操作会结束输出行,然后它会刷新缓冲区。
(3)字符直接量、字符串直接量和转义字符的关系
字符直接量和字符串直接量和转移字符的关系是一样的,唯一的区别是一个用双引号,一个用单引号。然而字符直接量和字符串字节量却是不同的,字符直接量是代表一个字符, 而 字符串直量则不是,而且字符串直接量中会用'\0'来作为字符串的结束标志,这是和C语言中的字符串一样的。
转移字符有如下 \t,\n,\b,\",\',\\。其中\t是tab,\n是换行符,\b是回退符。
(4) 限定名称和作用域运算符(::)
在上面那条语句中,名称std::cout是一个限定名称,它使用了::运算符。我们把::称为作用域运算符。左边是一个作用域的名称,就std::cout而言,这个作用域名称是std的名字空间。右边也是名称,这个名称是在左边命名的作用域中定义的。因此std::cout表示“在名字空间作用域std中的名称cout”
同时需要强调的是花括号也是一种作用域。现在我们通过这个例子学到了两种作用域:1.名字空间 2.花括号作用域。
习题答案:
0-0.
#include <iostream> int main() { std::cout << "Hello, world!" << std::endl; return 0; }
0-1
这个表达式是为了计算出3+4的结果。其没有副作用。
0-2
#include<iostream> int main( ) { std::cout << "This (') is a quote,and this ( \\ ) is a backlash." << std::endl; return 0; }
0-3
#include<iostream> int main() { std::cout << "0123456789012345678901234567890123456789" << std::endl; std::cout <<" " << "012345678901234567890123456789" << std::endl; std::cout <<" "<< "012345678901234567890123456789" << std::endl; std::cout << "\t" << "AAAAAAAAAAA" <<"\t"<< "AAAA" << std::endl; return 0; }
这题需要解释以下,运行下我写的程序可以很清晰的看出tab是缩进8个空格,那么第二tab怎么没有缩进8个空格。
那么其实tab鍵的设计原理是这样的,寻找最近的8的倍数,在之后输出,所以第一个最进的就是8,所以tab后,从8这个位置开始输出,而第二个,刚好是24,也就是此时按下tab能跳到的最近的是第24列,所在24列后输出
0-4.
#include <iostream> int main() { std::cout << "#include <iostream>\n" << "\n" << "int main()\n" << "{\n" << " std::cout << \"Hello, world!\" << std::endl;\n" << " return 0;\n" << "}\n"; return 0; }
0-5
不是一个有效程序。因为main函数后面没有花括号括起来。其下面的程序语句就无法确定是属于哪一个函数的。
0-6
是一个有效程序,因为main后要用花括号一层来括其其作用域
而剩下的花括号也可以一一找到后面的匹配,所以都能构成有效的作用域。
0-7
这个注释是错的,程序遇到/*开始寻找与它匹配的*/在这之间都为注释。所以这个注释是错的。
0-8
这个是没错的,//也是一种注释,是按照行来注释的,在它后面的所有任何字符都当作注释
0-9
#include<isotream> int main() { }
0-10
#include<iostream> int main( ) { std::cout << "\nH\ne\nl\nl\no\n,\nW\no\nr\nl\ndn\!n" << std::endl; return 0; }
Mon Dec 23 17:08:05
By ACReaper(苏威鹏)