第1章 快速入门
- main函数的返回值必须是int型。
- C++并没有直接定义进行输入输出的任何语句,这种功能是由标准库提供的。
- endl是一个特殊值,将它写入到输出流时,具有输出换行的效果,并刷新与设备相关联的缓冲区。通过刷新缓冲区,用户可以立即看到写入到流中的输出。
- 建议:定义变量是,应该给变量初始化。
第2章 变量和基本类型
- 建议:使用int整型和double浮点型,不易出错。
- C++支持两种初始化变量的形式:
复制初始化:使用等号
直接初始化:把初始化式放在括号中 - 建议:每个内置类型的对象都要初始化。
- 非const变量默认为extern,要使const变量能够在其他的文件中访问,必须显式地指定它为extern。
- 引用:引用就是对象的别名,引用主要用做函数的形参。引用在定义时必须初始化,且不能再次更改。
- const引用:指向const对象的引用。可以绑定到不同但相关的类型的对象或绑定到右值。而非const引用只能绑定到与该引用同类型的对象。
- 测试:
- typedef用来定义类型的同义词。
- enum
枚举提供过了一种替代方法,不但定义了整数常量集,而且还把他们聚集成组。
枚举成员本身就是一个常量表达式,不能枚举成员的值,常量表达式是编译器在编译时就能计算出结果的整型表达式。
枚举类型的对象的初始化或赋值,只能通过其枚举成员或同一枚举类型的其他对象来进行。 - 定义类:通常先定义该类的接口,即该类所提供的操作,通过这些操作,可以决定完成其功能所需要的数据,以及是否需要定义一些函数来支持该类的实现。
- 定义数据成员:只能指定该数据成员的名字和类型,初始化有构造函数完成。
- struct和class:默认情况下,struct的成员为public,class为private。
- 头文件:可以定义类、值在编译时就已知的const对象和inline函数。
第3章 标准库类型
标准库string类型
1. string对象的定义和初始化:
string末尾并不会添加’\0’结束字符,也不会复制字符串常量中的结束字符
2. string对象的读写:
从标准输入读取string:
读取并忽略开头所有的空白字符(空格、换行、制表符)
读取字符直至再次遇到空白字符,读取终止
用getline读取整行文本:
getline读取一行文本直到遇到换行符,但不包含换行符
getline并不忽略开头的换行符
3. string对象的操作:
1) size()函数:返回值必须为string::size_type类型,将其复制给int整型可能出现范围太小的问题。
2) +操作符:当进行string对象和字符串字面值混合连接操作时,+操作符的左右操作数必须至少有一个是string类型。
标准库vector类型
1. vector不是一种数据类型,而是一个类模板,可用来定义任意多种数据类型,如string string。
2. vector对象的定义和初始化
3. vector对象的操作
[]下标运算符:必须是已存在的元素才能使用下标操作符进行索引,通过下标操作符访问、修改元素的值,但不能添加新元素。
循环判断条件:C++程序员习惯优先选用!=而不是<来编写循环判断条件。
迭代器iterator
1. 迭代器:是一个检查容器内元素并遍历元素的数据类型。每一种容器都有自己的迭代器类型。
2. begin和end操作:begin返回指向容器第一个元素,end返回指向末端元素的下一个,并不指向容器中的任何元素。
3. *操作符:迭代器类型可使用解引用操作符来访问迭代器所指向的元素。
4. const_iterator:使用const_iterrator类型时,可以得到一个迭代器,它自身的值可以改变,但不能改变其所指向的元素的值。
5. 任何改变vector长度的操作都会使已存在的迭代器失效。
第4章 数组和指针
- 指针与迭代器的区别:指针用于指向单个对象,迭代器用于访问容器中的元素。
- 提醒:很多运行时错误都是源于使用了未初始化的指针。
- void*:不允许void*指针操纵它所指向的对象。
- 指针和引用的区别:
引用总是指向某个对象,定义式必须初始化
给引用赋值修改的是该引用所关联的对象的值
第5章 表达式
- %求余:操作数只能是整型,包括bool char short int long类型。
- && ||:短路求值策略
- 建议:++ – 使用前置操作,性能问题
- new delete:动态创建和释放单个对象。
创建类对象时会用该类的默认构造函数初始化。值初始化的()必须置于类型值后面,而不是变量后面。
一旦删除了指针所指向的对象,立即将指针置为0,避免成为悬垂指针。
第5章 语句 - 常量表达式:字面值常量、const变量、enum常量成员
- 定义数组长度、switch语句中case对象,都需要常量表达式。
int main(void)
{
#define ONE 1
const int consti = 2;
enum e
{
enuma,
enumb=2,
enumc
};
for (int i = 0; i < 4; i++)
{
switch (i)
{
case ONE:
cout << "ONE = " << ONE << endl;
break;
case consti:
cout << "consti = " << consti << endl;
break;
case enumc:
cout << "enumc = " << enumc << endl;
break;
default:
cout << "default handle:i=" << i << endl;
break;
}
}
int a1[ONE] = { 0 };
int a2[consti] = { 0 };
int a3[enumc] = { 0 };
cout << "a1:" << sizeof(a1) << endl;
cout << "a2:" << sizeof(a2) << endl;
cout << "a3:" << sizeof(a3) << endl;
return 0;
}
3. continue和break:
continue:导致最近的循环语句的当次迭代提前结束。只用于循环语句。
break:将程序的执行权传递给紧接被终止语句之后的语句。只用与循环语句和switch语句。
4. 异常:运行时的不正常。
5. 异常处理:throw表达式、try块、异常类
1) throw表达式:抛出异常,用于错误检测
2) try块:在try块中执行代码锁抛出的异常(throw),通常被一个catch子句处理
3) 异常类:用来在throw和对应的catch之间传递有关的错误信息
6. 使用预处理器进行调试:
FILE 文件名
LINE 当前行号
TIME 文件被编译的时间
DATA 文件被编译的日期
7. 断言预处理宏(assert):
形式:assert(expr)
只要NDEBUG预处理变量未定义,assert宏就会求解表达式expr,如果结果为false,assert输出信息并且终止程序的执行。
在成品中,assert语句不做任何工作,没有任何运行时代价。
assert仅用于检查确实不可能的条件,这只对程序的调试有帮助,不能用来代替运行时的逻辑检查,也不能代替对程序可能产生的错误的检查。
第7章 函数
- 非引用形参:复制实参的值,有三个局限性:
当需要在函数中修改实参的值
当大型对象时,复制对象付出时间和空间代价过大
当没有办法实现对象的复制时 - 引用形参:实参的别名
非const引用形参只能与完全相同类型的非const对象关联。
const引用形参可以与const和非const对象关联 - 通过引用传递数组:如果形参是数组的引用 ,编译器不会将数组实参转化为指针,而是传递数组的引用本身,编译器会检测数组的大小。
引用数组:&arr[10],本质是一个数组,每一个数组元素都是一个引用
数组引用:(&arr)[10],本质是一个引用,一个有10个元素的数组的引用 - 多维数组的传递:
指针数组:*arr[10],本质是一个数组,每一个数组元素都是一个指针
数组指针:(*arr)[10],本质是一个指针,指向一个有10个元素的数组 - 返回非引用类型:在调用函数是创建临时变量,被调用函数将返回值赋值给临时变量。
- 返回引用类型:没有复制返回值,返回的是对象本身。
- 内联函数:
内联函数避免函数调用的开销
内联函数应该在头文件中定义
内联机制适用于优化小的,只有几行的而且经常被调用的函数。
内联说明对于编译器来说只是个建议。 - 类的成员函数:
编译器隐式地将类内定义的成员函数当作内联函数
每一成员函数都有一个额外的、默认的形参this,this初始化为调用的对象的地址
常成员函数(const)不能修改调用该函数的对象 - 重载函数:
同一作用域内,具有相同名字而形参不同的函数,成为重载函数
函数不能仅仅基于不同的返回类型而实现重载
const形参和非const形参的等价性仅适用与非引用形参
// const形参是引用或指针时,可以实现函数重载
void fun3(const string &s) {}
void sun3(string &s) {}
// 函数编译能通过,但是调用时出错,产生二义性
// error C2668: 'fun2': ambiguous call to overloaded function
void fun2(const string &s){}
void fun2(string s){}
// const形参是非引用时是等价的,不能实现重载
// error C2084 : function 'void fun1(const std::string)' already has a body
void fun1(const string s) {}
void fun1(string s) {}
- 指向函数的指针:bool (*pf)(const string &,const string &)
#include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef bool(*pf)(const int &, const int &);
bool fun(const int &a, const int &b)
{
if (a > b)
{
cout << "the max num is : " << a << endl;
return true;
}
else
{
cout << "the max num is : " << b << endl;
return false;
}
}
//函数指针形参
void fun1(bool fun(const int &, const int &))
{
fun(10, 20);
}
void fun2(bool(*fun)(const int &, const int &))
{
fun(30, 20);
}
//返回指向函数的指针
pf fun3(int i, int j)
{
pf pfun = fun;
pfun(i, j);
return pfun;
}
int main(void)
{
//初始化和赋值
pf pfun = NULL;
pfun = fun;
//通过指针调用函数
pfun(1, 2); //含蓄地调用
(*pfun)(3, 2); //明确地调用
//函数指针形参
fun1(pfun);
fun2(pfun);
//返回指向函数的指针
pf pfun3 = fun3(100, 200);
pfun3(300, 200);
return 0;
}
第8章 标准I/O库
- IO标准库
cin(发音为 see-in):读入标准输入的 istream 对象。
cout(发音为 see-out):写到标准输出的 ostream 对象。
cerr(发音为 see-err):输出标准错误的 ostream 对象。cerr 常用于程序错误信息。
>> 操作符,用于从 istream 对象中读入输入。
<< 操作符,用于把输出写到 ostream 对象中。 - 条件状态:标记给定的IO对象是否处于可用状态,或者碰到了哪种特定的错误。
所有流对象都包含一个条件状态成员,该成员由setstate和clear操作管理。clear操作将条件重设为有效状态。setstate操作可打开某个指定的条件。
流的状态由bad fail eof good操作揭示。 - 输出缓冲区刷新:
flush:刷新缓冲区
ends:添加null字符,刷新缓冲区
endl:添加换行符,刷新缓冲区