C++ primer
第1章 开始
- main函数的返回类型必须为int
- main的返回值被用来指示状态。返回值0表明成功,非0的返回值的含义由系统定义,通常用来指出错误类型。
- 执行完一个程序后,可以用过echo命令获得其返回值
1//test.cpp
#include <iostream>
using namespace std;
int main() {
return -1;
}
$ g++ test.cpp -o app
$ ./app
$ echo $?
255
- cerr:标准错误,clog:输出程序运行时的一般性信息
- endl是一个被称为操作符的特殊值,效果是结束当前行,并将设备关联的缓冲区中的内容刷到设备中。
- std::表示定义在名为std的命名空间(namespace)中,标准库定义的所有名字都在命名空间中。
- 作用域运算符::,作用之一为访问命名空间中的名字。
- 当遇到文件结束符(end-of-file)或者遇到一个无效输入时,istream对象的状态会变成无效,处于无效状态的istream对象会使条件变为假。
- windows ctrl+z
- unix ctrl+d
- 包含来自标准库的头文件时,使用<>包围头文件。不属于标准库的,使用""
- 使用调用运算符()来调用一个函数。
第2章 变量和基本类型
-
大多数计算机将内存中的每个字节与数字(被称为“地址”)关联起来
-
字符串类型被分为char、signed char、unsigned char,char 和 signed char不一样。
-
在算术表达式中不要使用char 或者 bool,因为类型char在一些机器上是有符号的,而在另一些机器上面又是无符号的。
-
需要使用一个不大的整数,需要明确指定它的类型是signed char 或者 unsigned char
-
signed char c2 = 256 // c2的值是未定义
-
-
执行浮点数运算使用double,因为float 通常精度不够而且双精度浮点数和单精度浮点数的计算代价相差无几。
-
unsigned u1 = 42, u2 = 10; std::cout << u2 - u1 << std::endl; // 正确,不过,结果是取模后的
-
如果表达式中既有带符号类型又有无符号类型,当带符号类型取值为负值时会出现异常结果,这是因为带符号数会自动转换成无符号数。
-
由单引号括起来的字符称为char型字面值,双引号括起来的零个或者多个字符则称为字符串字面值。
- 编译器通常在每个字符串字面值的结尾处添加一个空字符(‘\0’)
-
如果反义斜线\后面跟着的八进制数字超过3个,只有前3个数字与\构成转义序列
-
nullptr是指针字面值
-
初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除,而以一个新值来代替。
-
double price = 109.9, discount = price*0.6 // 正确,price先被定义并赋值,随后被用于初始化discount
-
-
定义在函数体内的内置类型的对象如果没有初始化,则其值是未定义。类的对象如果没有显示初始化,则其值由类确定。
-
如果想声明一个变量而非定义它,就在变量名前添加关键字extern,而且不要显示地初始化变量
-
extern int i; // 声明i而非定义i int j;// 定义j extern double pi = 3.1416; // 定义, 在函数体内部,如果试图初始化一个声明,会引发错误。
-
变量能且只能被定义一次,但可以被多次声明。
-
-
变量名一般用小写字母,用户自定义的类名一般以大写字母开头
-
C++中大多数作用域都以花括号分隔。
- 名字的有效区域始于名字的声明语句,以声明语句所在的作用域末端结束。
- 作用域中一旦声明了某个名字,它所嵌套的所有作用域中都能访问该名字。同时允许在内层作用域中重新定义在外层作用域已有的名字。
-
引用,指的是左值引用
-
int &refval2; // 报错;引用必须初始化
-
-
引用并非对象,相反的,它只是为一个已经存在的对象所起的另外一个名字。
-
因为引用本身不是一个对象,所以不能定义引用的引用。
-
大多数情况下引用要与之绑定的对象严格匹配
-
int &refval = 10; // 错误:引用类型的初始值必须是一个对象 double val = 3.14; int &refval2 = val; // 错误:此处引用类型的初始值必须是int型对象
-
-
指针
-
指针本身就是一个对象,允许对指针赋值和拷贝,在指针的生命周期内可以指向不同的对象。
-
指针无须在定义时赋初值,在块作用域内定义的指针如果没有被初始化,将拥有一个不确定的值。
-
不能定义指向引用的指针,因为引用不是对象,没有实际的地址。
-
对指针解引用对得到所指向的对象,如果给解引用的对象赋值,实际上就是给指针所指的对象赋值。
-
int *p; // *紧随类型名出现,因此是声明的一部分,p是一个指针 *p = i; // *出现在表达式中,是一个解引用符
-
nullptr是一种特殊类型的字面值,它可以被转换成任意其他的指针类型。过去的程序会使用名为NULL的预处理变量来给指针赋值,这个变量在头文件cstdlib中定义,它的值就是0
-
int *p1 = nullptr; int *p2 = 0; // 以上两种方式都可以用来生成空指针 // 需要先 #include <cstdlib> int *p3 = NULL; // 现在的C++程序最好使用nullptr,同时尽量避免使用NULL // 把int变量直接赋值给指针是错误的操作,即使int变量的值恰好等于0也不行 int zero = 0; p1 = zero; // 错误:不能把int变量直接赋值给指针
-
预处理变量不属于命名空间,它有预处理器管理,因此可以直接使用预处理变量而无须在前面加上std::
-
当使用预处理变量时,预处理器会自动将它替换为实际值,因此使用NULL初始化指针和使用0初始化指针是一样的。
-
-
void*是一种特殊的指针类型,可用于存放任意对象的地址。
- 不能直接操作void*指针所指的对象,因为不知道该对象是什么类型,也就无法确定能在这个对象上做哪些操作。
-