C++历史
美国新泽西州贝尔实验室Bell Lab
由C++之父Bjarne Stroustrup(丹麦)发明
C++标准库
标准函数库
输入/输出 I/O
字符串和字符处理
数学
时间、日期和本地化
动态分配
宽字符函数
面向对象类库
标准的 C++ I/O 类
String 类
数值类
STL 容器类
STL 算法
STL 函数对象
STL 迭代器
STL 分配器
本地化库
异常处理类
杂项支持库
namespace与class的区别
namespace主要是为了防止多个开发人员开发时命名重合。
namespace可以被再次打开并添加新成员。但class不允许。
C++引用
1.引用必须被初始化,指针不必
2.引用初始化后不能被改变,指针可以改变所指的对象
3.不存在指向空置的引用,存在指向空值的指针
引用的功能指针都能实现,不过指针不安全,写的时候一不注意就是BUG,用引用相对安全。
const
const int x=3; 将x变成常量,值为3;后续无法对x赋值,否则报错。
常量指针(const int * p、int const * p) --------*p为常量
指针常量(int * const p) ----------p为常量
函数参数默认值
例:void fun(int i,int j=5,int k=10); 有默认参数值的参数必须在参数表的最右端
内联函数inline
在调用时通过将函数体直接插入调用处来实现的,这样可以大大减少由函数调用带来的开销(特别是循环)
内存分区
栈区
int x=0; int* p=nullptr;
堆区
int* p=new int[20];
全局区(或者叫静态区)
全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域
常量区
string str =“hello”;
注意const a=10; 在函数内a放在栈区,这种写法主要是为了防止程序员在后续的代码中误操作a变量而添加的一个约束条件,并不会影响它存放的位置
代码区
用于存储程序编译连接后生成的二进制机器码指令的内存区域。该部分内容可通过反汇编操作将机器码转换为汇编语言。
构造函数
有参数时 Teacher t1(10);
巧用this指针时this会放前 Teacher(this,10);
拷贝构造函数
- 当用类的一个对象去初始化该类的另一个对象(或引用)时系统自动调用拷贝构造函数实现拷贝赋值。
- 若函数的形参为类对象,调用函数时,实参赋值给形参,系统自动调用拷贝构造函数。
- 当函数的返回值是类对象时,系统自动调用拷贝构造函数。
Teacher::Teacher(const Teacher &tea){};
移动构造函数
专门处理这种用a初始化b后就将a析构的情况
避免了新的空间的分配,大大降低了构造的成本
Teacher::Teacher(Teacher && moveFrom){};
赋值函数
Teacher& operator = (const Teacher &tea) //const是不希望通过引用改原数据;一般不写出tea
{ if(this!=&t) { data=tea.data; } //避免自己给自己赋值
return *this;
}
移动赋值函数
Teacher& operator = (Teacher && moveFrom){}
this指针
Teacher t1; 则this 等价于 &t1
成员函数使用和成员变量同名的参数时,有this->的是成员变量
公有继承
public变public
protected变protected
private变无法访问
保护继承
public变protected
protected变protected
private变无法访问
私有继承(C++默认)
public变private
protected变private
private变无法访问
is a
只能用派生类初始化基类,不能反过来,然后派生类中基类没有的数据成员会被截断
基类指针指向派生类时也会截断派生类中基类没有的数据成员
虚继承
菱形继承时会导致 最基类 空间冗余
class 工人 : virtual public 人{};
class 农民 : virtual public 人{};
class 农民工 : public 工人 , public 农民{};
友元函数友元类
类的友元函数是定义在类外部,但有权访问类的所有private成员和protected成员。
友元类的整个类及其所有成员都是友元。
成员函数重载的第一个参数为this指针(经常不写出)
输出运算符<<重载由于要求第一个参数必须为 ostream &a,所以不能使用成员函数重载,而使用友元函数重载。
静态的没有
虚函数
1.定义派生类对象,并调用对象中未被派生类没有的基类函数A。同时在该函数A中,又调用了已被派生类覆盖的基类函数B,那此时将会调用基类中的函数B;如果该函数是虚函数(基类的函数加virtual),则会调用派生类中的该函数。
2.在使用指向派生类对象的基类指针,并调用派生类中的覆盖函数(p->fun())时,如果该函数不是虚函数,那么将调用基类中的该函数;如果该函数是虚函数(基类的函数加virtual),则会调用派生类中的该函数。
tips:基类指针指向派生类才有多态性的展现
基类的同名函数加了virtual后,派生类的同名函数加不加virtual都一样的,加了可以增强可读性
placement new
char* buf = new char[sizeof(A) * 3];//申请了3个A的内存
A* pc = new(buf)A();//运用申请好的buf的内存,在buf上赋值
虚析构函数
基类中析构函数加virtual,delete基类指针时会连同删除掉派生类所有在堆中申请的内存
基*p=new 派生(); delete p; p=nullptr; //不怕内存泄露
基类的析构函数一定要加 virtual !!!!
虚函数表
类实例化后会产生一个虚函数表指针,指向虚函数表,虚函数表放着虚函数的指针
若派生类覆盖基类,则虚函数表内的虚函数指针就不指向基类的虚函数了
重载
同类内,同名,不同参
覆盖
分别在基类派生类,同名,同参,加virtual
隐藏(注:基类指针指向new的派生类对象时调用的是基类的函数)
分别在基类派生类,同名,同参时无virtual,不同参时有无virtual皆可
纯虚函数抽象类接口类
virtual int fun()=0; //纯虚函数
含有纯虚函数的类为抽象类,无法实例化对象
抽象类的派生类需要实现所有基类的纯虚函数,才能实例化对象
全为纯虚函数,无成员函数的类,叫接口类
STL(Standard Template Library)标准模板库
6大组件
Container(容器)
顺序容器vector、list链表、deque双队列
关联容器
map映射:
map<int,string>m;`
pair<int,string>p(10,"guangzhou");
m.insert(p);
cout<<m[10]<<endl;
输出得guangzhou
set集合:暂无
Iterator(迭代器)
输入迭代器 读,不能写,只支持自增
输出迭代器 写,不能读,只支持自增
前向迭代器 读和写,只支持自增
双向迭代器 读和写,支持自增和自减
随机访问迭代器 都和写,支持完整的迭代器算术运算;
迭代器是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址
int main(){
vector vec1; vec1.push_back("hello");
vector<string>::iterator citer1=vec1.begin();
for(;citer!=vec.end();citer1++) { cout<<*citer1<<endl; }
}
Adapter(适配器)
不改变原有接口下,转换成我们期待的接口
stack栈、queue单队列、priority_queue优先队列
Algorithm(算法)
只读算法(查找、搜索、统计)
可变序列算法(复制,变换,替换,填充,移除和随机生成等)
排序算法
关系算法(求最值)
堆算法(堆排序)
其他是一些容器特有的算法
Function object(函数对象)
Allocator(分配器)
分配器就用于处理容器对内存的分配与释放请求
常函数
void fun() const {}
1.可以使用数据成员,不能进行修改,对函数的功能有更明确的限定;
2.常对象只能调用常函数,不能调用普通函数;
3.常函数的this指针是const CStu*
lambda表达式
int main()
{
int a = 10;
int b = 20;
auto func = [=](type i)->int {
switch (i)
{
case add: return a + b;
case sub: return a - b;
case mul: return a * b;
case divi: return a / b;
}
};
cout<<func(add)<<endl;
}
Functional Programming函数式编程
相对面向对象编程的另外一种看待事物的方式,建议知乎搜索下看看哦
std::bind
用法一:
减少调用参数
auto fun = [](int *array, int n,int num){}
auto newfun = bind(fun, _1, _2, 5);
则newfun()仅需传入2个参数,第三个参数固定为int 5
用法二:
更改参数调用顺序
多线程
创建
#include <pthread.h>
pthread_create (thread指针, attr属性, start_routine运行起始地址, arg运行函数的参数)
终止
#include <pthread.h>
pthread_exit (status)
智能指针
auto_ptr
unique_ptr
shared_ptr
weak_ptr