目录
第1章 开始
- 输入运算符(>>)与输出运算符(<<)类似,接受一个istream作为其左侧运算对象,接受一个对象作为其右侧运算对象。输入与输出运算符返回其左侧运算对象作为其计算结果。因此下面两种写法等价.
cin>>v1>>v2;
(cin>>v1)>>v2; - 成员函数:成员函数是定义为类的一部分的函数(member function),有时也被称为方法(method)。
第2章 变量和基本类型
- 当赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数。当赋给带符号类型一个超出它表示范围的值时,结果是未定义的。(可能正确也可能不正确也可能崩溃)。
- 如果两个字符串字面值位置紧邻且仅由空格、缩进和换行符分隔,则它们实际上是一个整体。
- 初始化不等于赋值,赋值是把原来的值擦除以一个新值代替,初始化是创建变量时赋予其一个初始值。
- 使用extern可以声明一个变量但是不定义它。如:
extern int i; //声明i而非定义i
int i ; //声明并定义i
extern double pi = 3.1416 //定义
- 作用域:同一个名字在不同的作用域中可能指向不同的实体。名字的有效区域始于名字的声明语句,以声明语句所在的作用域末端为结束。
- 引用:为对象起了另外一个名字。(引用并非对象,只是为一个已经存在的对象所起的另外一个别名),也不能定义指向引用的指针。
int ival = 1024;
int &refval = ival; //refval指向ival(是ival的另一个名字)
int &refval2; //报错:引用必须被初始化,引用初始化以后无法绑定到其他对象上
- 在定义多个引用和指针时候每个前面都要加&(或*),如:
int *a,*b;
const int a
与int const a
等价
const int *a
与int const * a
等价,与int * const a
不等价,前者可以指向别处,但是不能改指定的值,后者不可以指向别处,但是可以修改指针指定的值。const int * cosnt a
则既不能指向别处,也不能修改指定的值。- 对常量引用只能使用引用常量,即
const int ci = 1024;
const int &r1 = ci
正确
int &r2 = ci
错误,试图让一个非常量引用指向一个常量对象
第3章 字符串、向量和数组
- 使用cin读入字符串string时,遇到空白字符就停止了。这时使用getline(cin,s)可以读取一整行。
- C++语言中的字符串字面值并不是标准库类型string的对象。
- 对于字符串s,使用for(auto c:s) 要想修改字符串,必须在c前加&(引用)
vector<int\>::iterator it;
//it能读写vector<int>的元素
vector<int\>::const_iterator it2;
//it2只能读元素,不能写元素int *(&arry)[10] = ptrs
//arry是数组的引用,该数组含有10个int指针。- 注意:大多数常见的安全问题都源于缓冲区溢出错误。当数组或其他类似数据结构的下标越界并试图访问非法内存区域时,就会产生此类错误。
第4章 表达式
第5章 语句
- try和throw和catch,将一段可能抛出异常的语句序列放在花括号里构成try语句块。throw表达式语句将控制权转移到相应的catch子句。catch语句负责处理代码抛出的异常。
第6章 函数
- 函数的返回类型不能是数组。
- 函数的形式参数使用引用可以避免拷贝,如果函数无须改变引用形参的值,最好将其声明为常量引用。
- 可以使用非常量初始化一个底层的const对象,但是反过来不行。
- 函数的返回值类型不能是数组。但可以返回指针数组。
int arr[10];
//arr是一个含有10个整数的数组
int (*p2)[10] = &arr;
//p2是一个指针,它指向含有10个整数的数组。- 返回指向函数的指针真绕啊。。。。。
第7章 类
- 定义在类内部的是隐式的inline函数。
- this是一个常量指针,我们不允许改变this中保存的地址。
- 引入const成员函数(在类成员函数参数列表之后加 const ),如果不加const ,则我们不能把this绑定到一个常量对象上。即:常量对象以及常量对象的引用或指针都只能调用常量成员函数。
- 当类中未声明任何构造函数时,编译器才会生成一个默认构造函数。
- 如果类内包含有内置类型或者复函类型的成员时,则只有当这些成员全都被赋予了类内的初始值时,这个类才适合于使用合成的默认构造函数。
- 对于struct关键字和class关键字,
struct
的默认访问权限是private
,class
的默认访问权限是public
。 - 可变数据成员mutable(mutable data member)永远不会是const,即使它是const对象的成员。
- 友元关系不具有传递性。
- 对于一个类
sales_data
,如果想定义一个使用默认构造函数进行初始化的对象,正确的写法如下:
sales_data obj;
//正确,调用默认构造函数
sales_data obj()
//错误,定义了一个函数而非对象 - 当在类的外部定义静态成员时,不能重复
static
关键字,该关键字只出现在类内部的声明语句中。 - 类的static(静态)成员变量不能在函数内定义(在全局中定义)。
第8章 IO库
此章暂跳
第9章 顺序容器
- 当将一个容器初始化为另一个容器的拷贝时,两个容器的容器类型和元素类型都必须相同。但是可以用迭代器拷贝不同容器类型的两个容器如下例。
list<string> authors = {"aa","bb","cc"};
deque<string> authlist = (authors.being(),authors.end());
- array(数组)容器的使用。内置数组不允许拷贝或对象赋值,但array允许。
- 除了array外,swap不对任何元素进行拷贝、删除或插入操作,因此可以保证在常数时间内完成。
vector<int> nums1(10); //10个元素的vector
vector<int> nums2(20); //24个元素的vector
swqp(num1,num2);
- 除了顺序容器以外,还有3个顺序容器适配器(adaptor):stack、queue、priority_queue。容器、迭代器和函数都有适配器。默认情况下:stack和queue是基于deque实现的。priority_queue是基于vector实现的。
第10章 泛型算法
- algorithm库的find函数用来查找一个容器中是否具有某个值。如:
vector<int> nums{1,2,3}
find(nums.begin(),nums.end(),2) //返回迭代器,如果查不到,返回nums.end();
accumulate
函数(算法)前两个参数是迭代器类型,表示求和的范围,第三个参数类型决定了函数中使用哪个加法运算符以及返回值类型。equal
函数(算法),将第一个序列的每一个元素与第二个序列中的元素进行比较,如果相等则返回true,否则返回false。
equal(rouster1.cbegin(),rouster2.cend(),router2.cbegin())
//router2中的元素数目数目至少与router1一样多。fill
写容器的算法,如:fill(vec.begin(),vec.end(),0)
//将每个元素重置为0- lambda表达式:可以理解为一个未命名的内联函数。具有如下形式:
[capture list] (parameter list) mutable -> return type{ function body }
其中:capture list(捕获列表)局部变量列表,通常为空。如果需要改变被捕获的值拷贝(非引用)变量的值,则需要添加mutable。
可以忽略参数列表和返回类型,但是必选包含捕获列表和函数体。
如:auto f = [] { return 42; }
调用方式:cout<<f()<<endl; //打印42
如果lambda的函数体包含任何单一return语句之外的内容,且未指定返回类型,则返回void
捕获列表只用于局部非static变量,lambda可以直接使用局部static变量和它所在函数之外声明的名字。
指定lambda的返回类型。
因为如果lambda体包含return以外的任何语句,则默认返回void。
- 标准库bind函数:可以修正函数的参数,也可以重新排列其顺序。
- 反向迭代器的目的是表示元素范围,如果把一个迭代器反向,则连个迭代器指向的不是同一个元素。
- algorithm里有太多函数了,简单过一遍,需要再查看吧。
第11章 关联容器
- map和set中的key类型必须可以比较,否则需要自己定义比较函数。
- 对于map,调用insert返回值是一个pair,pair->first是一个迭代器,pair->second是一个布尔型,false表示已经在map中,什么也不做。对于重复关键字的容器,只返回一个迭代器,因为一定会插入元素。
- 如果使用无序集合且类型不是内置类型,则需要重载哈希函数和相等判断函数。如果定义了==运算符,则可以只重载哈希函数。
第12章 动态内存
此节暂跳过大多数内容。
int *p = new int[0]
创建一个大小为0的静态数组对象是合法的。返回的指针是合法的,但是它并不指向任何元素,因此不能解引用。delete p;
//释放一个动态分配的对象
delete [] pa;
//释放一个动态分配的数组
第13章 拷贝控制
- 拷贝构造函数的参数必须是引用,否则便会造成无限递归(实参传递给形参时,又会调用拷贝构造函数)。
- 当指向一个对象的引用或指针离开作用域时,析构函数不会执行。
- 如果一个类需要自定义析构函数,几乎可以肯定它也需要自定义拷贝赋值运算符和拷贝构造函数。
第14章 操作重载与类型转换
- 相等运算符和不相等运算符应该定义其中一个,然后把另外一个委托给这个定义过的。
- 14.7后暂跳
第15章 面向对象程序设计
- 在c++语言中,当我们使用基类的引用(或指针)调用一个虚函数时将发生动态绑定。
- 对于动态绑定的引用(或指针),当调用虚成员时,会调用对应绑定对象重写的成员。如果不是虚成员,即使重写了,也只调用基类的成员。
- 在类名后面跟一个final可以防止该类被其他类继承。
final
说明符与override
说明符。(出现在形参列表以及尾置返回类型之后)
- override:使用该说明符,当该函数没有覆盖已有的虚函数时(比如参数不一致),编译器将报错。
- final:使用该说明符,如果把函数定义为final,则之后任何尝试覆盖该函数的操作都将引发错误。
- 除了覆盖继承而来的虚函数之外,派生类最好不要重用其他定义在基类中的名字。