数组名和指针 不一样的点,数组名是常量,不可用于 arrayname=arrayname+1运算。 数组名sizeof返回数组长度,指针返回本身长度。
数组名默认是指向第一个指针,&arrayName 是整个数组类型的指针,地址一样,但是+1运算,一个跨度是数组包含的类型,一个是整个数组的长度。
new 创建在堆或自由存储区中,其他在栈。 short (*p)[20] 类型为整个数组的指针, short *p[20] 类型short的指针数组。
三种管理数据内存方式:自动存储、静态存储、动态存储、线程存储(c++11)
自动存储:函数里定义的常规变量,函数结束时,消除。 放在栈上
静态存储:整个程序执行期间都存在。函数外定义或者使用static 可以实现该存储
动态存储:new创建 delete 删除 生命周期不受函数控制
c++11提供了auto关键字,避免复杂的指针创建 如**p = x 直接auto p=x
模板类vector 内部使用了new和delete进行管理,但是是自动的。 vector<int> xx (n)
模板类array(c++11) 存储在栈上,申明格式array<int,n> ad n不能是变量
数组必须逐个赋值,array可以整体赋值给另一个array。vector和array 对象有at方法 用来检查是否越界 xx.at(1),会产生更大的消耗。
指针形参不修改值最好加上const,防止修改值。const无法对指向指针的指针使用。因为会指向指针会修改数据。const修饰的指针可以改变指向,如果使用不能改变指向的指针 需要申明int * const finger = &xxx。可以双重申明 const int * const finger,这样不能改变指向的值,也不能改变指向的地址。
模板类array<int,9> 和 结构 默认传递值,数组默认传递地址。
auto 只能用于单值初始化,不能用于列表初始化、
虚函数内部运用了函数指针
int & xxx=xxx 引用必须初始化赋值,且绑定后不可更改绑定的地址。
函数参数 指针和引用的区别,指针是地址传递,引用是传递值的别名。
左值:常规变量和const变量,引用参数的函数,传入的应该是左值。
函数参数为引用类型且类型不一致需要转换时,传const是可以的,因为const目的是不改变值。传类型不符的是不可以的,因为生成的临时变量,改变值是临时变量无法改变引用的值,所以禁止了。
一般模板
template<typename T>
void Swap(T &,T &)
的匹配优先级小于显示具体化的模板版本
template <> void Swap<job>(job &,job &)
隐式实例化 就是一般的模板,遇到类型的时候会实列化模板(也就是函数)
显示具体化申明template <> void Swap<int>(int &,int &) (swap后面的<>可以不加) 命令编译器直接创建特定的实例
显示实列化申明template void Swap<int>(int,int)(区别在于template后面没有<>) 不用模板生成函数定义,使用专门为int类型显示定义的函数
decltype((xx)) 有括号代表的是计算左值的类型,左值类型是引用的类型 如double &
template<class T1,class T2>
auto gt(T1 x,T2 y) -> decltype(x+y){... return x+y;} 返回类型auto 可实现decltype在参数声明后面,处于x,y作用域。
包含头文件用 "xxx.h" 而不是<xxx.h>,如果用尖括号,编译器会在主机文件系统中的标准头文件中查找,双引号会首先在项目目录中查找,然后再去系统中查找。
extern 声明变量,不分配内存。通常是引用外部的静态外部链接变量。(静态变量分为静态无连接,静态外部链接,静态内部链接)
函数外声明初始化的变量时是外部链接,但是声明的const变量时是内部链接。可在const前面加上extern变成外部链接
函数内使用::x 代表使用x的全局变量版本。
如果结构申明时为const,想要改变结构内部的变量,则内部变量申明前面加上mutable
函数原型和定义中,加上static,链接性为内部,默认为外部。
定位new运算符,分配变量到指定的地址中 int * p1=new (buffer) int[10] int数组分配到buffer地址
默认情况下,将一个对象赋值给同类型的另一个对象时,c++会将原对象的每个数据成员的内容复制到目标对象的相应数据成员中去。
stock= Stock("xx","xx") stock之前已经定义过,这次操作会产生一个临时对象,并将值赋值到stock中去,然后调用析构函数,删除该临时对象。
只要方法不修改调用对象,都应该在方法后加上const 如:void show() const; void stock::show() const
接受一个参数的构造函数允许使用赋值对其初始化
enum xxx{x1} 枚举成员x1可以隐式的转为int : x1 enum class xxx{x1} 成员需要显式的转换: int(xxx::x1)
explicit 方法申明前加上这个 防止隐式转换
返回未经过new的对象时,如果返回的时指针,对象会被释放,返回的空指针。如果返回的时对象,返回的时候会创建该对象的副本返回,原对象释放。
友元函数是指类内部的函数,非成员函数(没有x::前缀)还可以访问类内部的成员(没有访问内部成员的,不必是友元),如cout<<xxx就是重载了<<的友元函数。
返回对象的引用& 返回指针*
显示转化,在类内部加上operator int() const 就可以 int(typename) 注意避免二义性
构造函数分为默认构造函数。复制构造函数(xxx(const xxx &))按值传递的时候触发,相当于把每个成员赋值给新的成员,这在析构函数释放资源的时候,如果调用了复制,会出异常,解决方法时重载复制构造函数,然后进行deep copy,如字符串进行std::strcpy,这样复制的对象释放不会影响原来的对象。赋值运算符重载(=),初始化的时候xxx d = ff,调用的时复制构造函数,d=ff调用的是赋值重载,class_name & class_name::operator=(const class_name &),默认和复制构造函数一样,复制成员。
空指针建议用nullptr 而非0(0是兼容以前的版本)
使用了virturl,使用引用或指针指向的对象的真实类型选择调用,如没有,根据引用或指针的类型调用。
虚函数的基类和派生类 都有虚函数表的数组,记录了虚函数的地址。每个函数一个地址组成的数组,派生类中也有基类的虚函数地址,如果派生类没有定义的话。称为动态联编,析构函数也应当申明虚函数,以便让派生类的资源得到释放。虚函数不支持重载(同函数名,不同的参数,派生类根据函数名覆盖,除非定义所有的基类的同名函数,这样就可以调用基类的虚方法),所以派生类的方法应与基类虚方法完全相同,返回类型如果是基类,可以修改为派生类(返回类型协变)
纯虚函数在函数定义后面加上 =0,则该类不能创建,只能被继承。然后再定义不同的继承类和他们的实现。
初始化列表包含多个项目时,按照属性声明的顺序进行初始化,而不是初始化函数后面的初始化列表的顺序。
类后面继承关键字为private 是私有继承,基类一切在子类中可使用,但是无法对外暴露。protect同理
(博客园丢失了一大半,未保存,心痛,弹个手机设置框,把我的都弄没了)友元、异常、string类、stl相关的(vector常用,其他的看场景)容器类:deque,list,queue,priority_queue,stack,vector,map,multimap,set,multiset,bitset,c++11新增forward_list(不支持随机访问,遍历)unordered_map,unordered_set,unordered_multiset,不将bitset视为容器,剩下的等到读第二遍再说
stl有四种关联容器set,multiset,map,multimap。set值类型和键相同,键唯一,multiset 键不唯一,内部pair类型。map 值与键类型不同,键唯一,multimap 键不唯一。
set<string> A,第二个参数可选,是对键用来排序比较的函数或对象,默认为less,set<string,less<string>> A; string s1[n]={....} set<string> A(s1,s1+n),与其他容器相似,set内部也有将一个迭代器区间作为参数的构造函数。
并集的方法 set_union(a.begin(),a.end(),b.begin(),b.end(),ostream_iterator<string,char> out(cout, " ")); 也可以插入到某个集合去,set_union(a.begin(),a.end(),b.begin(),b.end(),insert_iterator<set<string>>(c,c.begin)));
set_intersection()和set_difference()查找交集和获得两个集合的差,与set_union接口相同。
multimap count接受key参数放回值的个数。equal_range()key参数,返回迭代器,多个值。multimap<int,string> codes; codes.insert(pair<int,string>(415,"xxx"))
函数对象,也叫函数符,可以以函数方式和()结合。定义了operator()()的类。
for_each可以将指定的函数用于区间内的每个成员,for_each(a.begin(),a.end(),ShowReview),第三个参数可以是常规参数,也可以是函数符。但不能是函数指针,因为函数指针指定了参数类型,而容器可以包含任意类型。stl使用了模板来解决这个问题。for_each原型看上去是这样template<class InputIterator,class Funcation> Function for_each(InputIterator first,InputIterator last,Funcation f) ShowReview()原型:void ShowReview(const Review &) 对于不同的函数调用,Function参数可以表示具有重载的()运算符的类类型
slice类对象可作用数组,三个参数代表索引,索引数和跨距。如val[slice(1,4,3)]=10 将val的1,4,7,10 元素设置为10
缓冲区的存在是为了匹配不同速率的传输。streambuf为缓存区的管理提供了方法,ios_base类表示流的一般特征,是否可读取,是文本还是二进制流。ios类基于ios_base,其中包括了一个指向streambuf对象的指针成员。 ostream是从ios类派生而来,提供了输出方法。istream也是一样,提供了输入方法。iostream是基于之前两个类,提供了输入输出。