C++ Primer学习笔记(第一部分)
第2章 变量和基本类型
-
在命令行下看main函数的返回值,Unix为(echo $?),Windows为(echo %ERRORLEVEL%)。
-
为了兼容C语言,C++中所有的字符串字面值都由编译器自动在末尾添加一个空字符(null)。
-
多行字面值:在一行的末尾加一反斜线符号(\)可将此行和下一行当做同一行处理。
-
C++支持两种初始化变量的形式:复制初始化和直接初始化。复制初始化语法用等号(=),直接初始化则是把初始化放在括号中。
-
声明和定义:声明不能初始化,也不会分配空间。在C++语言中,变量必须且仅能定义一次,而且在使用变量之前必须定义或声明变量。
-
因为常量在定义后就不能被修改,所以定义时必须初始化。非const变量默认为extern,const变量默认非extern。
-
引用是别名:必须在定义引用时进行初始化。当引用初始化后,只要该引用存在,它就保持绑定到初始化时指向的对象,不可能将应用绑定到另一个对象。不能定义引用类型的引用。
-
const引用是指向const的引用,可以绑定到const对象、非const对象和右值。非const引用只能绑定到非const对象。
-
因为头文件包含在多个源文件中,所以不应该含有变零或函数的定义。但有三例外:头文件可以定义类、值在编译时就知道的const对象和inline函数。
第3章 标准库类型
-
不应该在头文件中使用using (namespace),因为头文件会影响包含它的源文件。
-
任何存储string的size操作结果的变量必须为string::size_type类型。特别重要的是,不要把size的返回值赋值给一个int变量。(为什么我测试可以???)
-
当进行string对象和字符串字面值混合连接操作时,+操作符的左右操作数必须至少有一个是string类型的。
-
vector:vector容器内的元素可以通过下标操作和迭代器进行访问修改,但添加元素必须通过vector的方法insert、push_back才行。
-
const_iterator vs const 的iterator:const_iterator是指迭代器指向的内容的值不能改变,用来只读vector;const的iterator是指迭代器不能改变,很少用到。
-
任何改变vector长度的操作都会使已存在的迭代器失效。例如,再调用push_bach之后,就不能再信赖指向vector的迭代器的值了。
-
string、vector、bitset是由标准库提供的类型,所以他们都有相应的方法;C++提供的内置类型int、数组、指针等都没有提供方法。
第4章 数组和指针
-
数组维数必须用值大于1的常量表达式定义,不允许数组直接复制和赋值。
-
指针保存0值,表明它不指向任何对象,所以删除指针后置0是个好办法。
-
C++提供了一种特殊的指针类型void*,它可以保存任何类型对象的地址。void*指针只支持几种有限的操作:与另一个指针进行比较;向函数传递void*指针或者从函数返回void*指针;给另一个void*指针赋值。不允许使用void*指针操纵它所指向的对象。
-
指向const对象的指针和const指针:指向const对象的指针(const int * pi)不能通过该指针修改指向对象的值;const指针(int *const pi)指针本身不能变。
指针和引用:引用是别名,必须在定义时初始化,且定义后不能再绑定到其他对象。
-
C风格字符串:char数组,且以null结束。char ca[]={'c','+','+','\o'};char *ca1=”primer”;
-
用new创建动态数组:int size=get_size();int *p=new int[size];
用delete释放空间:delete [] p;([]必须,数组的释放不同一般指针的释放)
-
int *ip[4]:声明了一个4维度的指针数组
int (*ip)[4]:声明了一个指向数组的指针,可以迭代二维数组。
第5章 表达式
-
sizeof操作符的作用是返回一个对象或类型名的长度,返回值的类型为size_t。数组ia的元素个数:int size=sizeof(ia)/sizeof(*ia);
-
逗号表达式是一组由逗号分隔的表达式,这些表达式从左向右计算。逗号表达式的结果是其最右边表达式的值。
-
类型转换(分隐式转换和显式转换)。有四种强制类型转换符:static_cast、dynamic_cast、const_cast、reinterpret_cast。dynamic_cast操作符用于将基类类型对象的引用或指针转换为同一继承层次中其他类型的引用或指针。const_cast用于转换掉表达式的const性质。static_cast能显式完成编译器隐式执行的任何类型转换。reinterpret_cast通常为操作数的位模式提供较低层次的重新解释。
旧式强制转换:type (expr) 或 (type) expr两种形式。
第6章 语句
-
Switch case:case标号必须是整型常量表达式(case 3.14: 和 case ival:就不行)。在switch内部要定义常量,必须用块结构(防止影响其他case)。
-
标准异常类定义在四个头文件中:
-
exception头文件定义了最常见的异常类,它的类名是exception。这个类只通知异常的产生,但不会提供更多的信息。
-
stdexception头文件定义了几种常见的异常类:runtime_error, range_error, overflow_error, underflow_error, logic_error, domain_error(参数的结果值不存在), invalid_argument, length_error, out_of_range
-
new头文件定义了bad_alloc异常类型,提供因无法分配内存而由new抛出的异常。
-
type_info头文件定义了bad_cast异常类型,dynamic_cast失败抛出的异常。
-
-
预处理器定义了四种在调试时非常有用的常量:
_ _ FILE_ _ 文件名
_ _LINE_ _当前行号
_ _TIME_ _ 文件被编译的时间
_ _DATE_ _文件被编译的日期
第7章 函数
-
形参的初始化与变量的初始化一样:如果形参具有非引用类型,则复制实参的值;如果形参为引用类型,则它只是实参的别名。
-
如果使用引用形参的唯一目的是避免复制实参,则应将形参定义为const引用。
-
引用指针的形参:void ptrswap(int *&v1,int *&v2)
-
c++程序员倾向与通过传递指向容器中需要处理的元素的迭代器来传递容器。
-
数组当形参时,非引用(起始是传递指针,能改变数组的内容)会忽略数组第一维。通过引用传递数组: void printValue(int (&arr) [10])(括号是必须的)
-
理解返回引用至关重要的是:千万不能返回局部变量的引用。
-
既可以在函数声明也可以在函数定义中指定默认实参。但是,在一个文件中,只能为一个形参指定默认实参一次。通常,应在函数声明中指定默认实参,并将该声明放在合适的头文件中。
-
内联函数应该在头文件中定义,这一点不同于其他函数。在头文件中加入或修改内联函数时,使用了该头文件的所有源文件都必须重新编译。
-
指向函数的指针:bool (*pf)(const string &, const sting &)(*pf两侧的圆括号是必需的)。函数指针只能通过同类型的函数或函数指针或0值常量表达式进行初始化或赋值。如 bool lengthCompare(const sting &, const string&);pf=lengthCompare;调用时可以:pf(“hi”,”bye”) 或 (*pf) (“hi”,”bye”)。
第8章 标准IO库
-
I/O对象不可复制或赋值,故函数参数和返回值只能是I/O对象的指针或引用。
-
刷新缓存区:使用endl(插入换行符), flush(不添加任何字符), ends(插入null), 使用unitbuf操作符(cout<<unitbuf<<”result”<<nounitbuf;);再就是把输入输出绑定在一起(cin.tie(&cout))。
-
如果程序员需要重用文件流读写多个文件,必须在读另一个文件之前调用clear清除该流的状态。