目录
细节
堆栈
关于调试
关于new和构造
读写文件或数组
输入输出
关于重载
关于模板
类型转换
关于const
字符串与int、double转换
访问权限
C语言独有
string类
内置数据结构
优先队列
仿函数与谓词
关于lambda
内建仿函数
STL算法
遍历
查找
排序
拷贝、替换
算数生成(包含numeric)
集合
细节
Short:2 int:4 long:4 long long:8 float:4 double:8 char:1 bool:1 指针:4
unsigned int : 0~4294967295
int : 2147483648~2147483647
unsigned long :0~4294967295
long : 2147483648~2147483647
long long(__int64):-9223372036854775808~9223372036854775807
unsigned long long(unsigned __int64):0~1844674407370955161注意有模(MOD)的时候定义一个const变量,指数可以用1e9+7(即pow(10,9)+7)的格式表示,而数据的表示范围如果达到1e9,一般都要用long long
类成员变量所占空间对齐
3e2=3x102
memset()函数原型是extern void *memset(void *buffer, int c, int count)
清空数组: memset(buffer, 0, sizeof(buffer))
static成员需要类外初始化
返回值为引用时,不调用复制构造函数
int *a[5]:数组名是a,每个元素为指针类型
int (*a)[5]:数组名是a,每个元素是数组类型
当一个cin对象作为条件选择、循环等的控制表达式时,输入Ctrl+Z可终止循环(cin的返回值依然是cin对象)
闰年二月29天,平年二月28天
lcm(a,b)用于求a和b的最小公倍数
gcd(a,b)用于求a和b的最大公因数
分文件:
模板放在.hpp文件中
cpp中引入该头文件
引用作参数:
1.防止对象所占空间太大而调用复制构造函数
2.可以直接对该对象进行操作
tuple
a:三元组,获取第一个int型变量->get<0>(a)
堆栈
C++是编译性语言,编译后生成.exe可执行文件
有:
代码区:只读、共享、存放CPU执行的二进制指令
全局区:存全局变量、静态变量、常量
常量区:存const修饰的常量
栈:存局部变量、形参
堆:存数组、对象
JAVA是解释性语言,编译后生成.class文件,可在多系统(Windows,Mac,Linux等)执行(跨平台)
有:
堆:存数组、对象
栈:局部变量、形参
方法区:常量池(存常量、字符串)、类加载信息
查看运行类型
C++:typeid(对象).name()
JAVA:对象.getclass().simplename()
关于调试
Clion调试:
F8:下一行 F7:进入函数 F9 :跳转到下一断点 Shift+F8:跳出函数
VS调试:
F10:下一行 F11:进入函数 Shift+F11:跳出函数 Ctrl+K+F:格式化
关于new和构造
构造函数的初始化列表是专门用来初始化成员对象的
Date d与Date * p=new Date没有括号(若有默认为函数声明),有参数时调用构造函数才有括号
注意:new出来的东西要调用delete才会析构,而直接定义的如A a退出main函数时会自动调用析构
Base *pTest2 = new Derived(); //Base类的指针(多态实现:父类指针或引用指向子类对象)
pTest2->DoSomething();
delete pTest2;
为了防止仅调用Base的析构而不调用Derived的析构造成内存泄漏,故Base类的析构函数要用virtual修饰(构造时先构造Base再构造Derived,析构时先析构Derived,如果new出来的是数组,注意用delete[]全部析构)
注:想要重写一个函数,必须所有东西严格一样,不能多或少一个const或者static
对象数组初始化:{{},{},{},{}~}——{}中的参数调用该类对应的构造函数
自定义二维数组构造器:
Int **p;
Array2(int a, int b) {
m = a;
n = b;
p = new int* [m];
for (int i = 0; i < m; i++) {
p[i] = new int[n];
}
}
class Person {
public:
Person operator+(const Person& p) {
Person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;//参数对象也可直接访问私有成员
return temp;
}
private:
int m_A;
int m_B;
};
拷贝构造函数(const A& a)三种调用情况:
- 用对象初始化另一对象
- 对象做参数
- 返回局部变量
Person p2=Person(p1);
Person p3=p1;
Person p4(p1);
Sample a=b调用拷贝构造函数
Sample a;
a=b指向同一对象,地址复制
析构函数只能有一个,不能重载
当指针属性在堆中开辟空间,就自己提供拷贝构造函数,否则系统提供的默认复制构造函数是浅拷贝,会带来重复释放堆区的问题。
浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。
如:String中有char* p,则拷贝构造函数中需要p=new char[strlen(a.p)+1]; strcpy(p,a.p);
自定义二维数组构造器:
Int **p;
Array2(int a, int b) {
m = a;
n = b;
p = new int* [m];
for (int i = 0; i < m; i++) {
p[i] = new int[n];
}
}
读写文件或数组
文本文件(ASCII码存):
- 创建 fstream(读是ifstream,写是ofstream) 对象
- 打开文件 open("文件路径",打开方式(in,out,app,binary))
- 判断是否打开 is_open()
- 写 ofs<<"~"
- 读while(ifs>>数组) 读取字符串若有空格或回车则停止,可通过getline(ifs,str)进行读取
- 关流 close()
二进制文件(二进制存):
- 创建 fstream(读是ifstream,写是ofstream) 对象
- 打开文件 open("文件路径",打开方式(in,out,app,binary必选))
- 判断是否打开 is_open()
- 写 ofs.write((const char*)&a,sizeof(a))--a可以是对象
- 读ofs.read((char*)&p,sizeof(p))
- 关流 close()
cin.get(数组名(char[]),大小,(结束符)): 若无结束语,遇到回车或达到(大小-1)则停止读取。
cin.get():其实就是C语言里的getchar()读取一个字符
cin.getline(数组名(char[]),大小,(结束符)):若无结束语,遇到回车或达到(大小-1)则停止读取。
以上结束符默认为enter,遇到结束符时剩余字符会停留在输入缓冲区(rdbuf),且结束符丢弃
getline(cin/ifs,str):读取每一行(包括空格)并存入str。
cin和cout默认是绑定(若要输入则先要把缓冲区的东西输送到目的地)的,通过cin.tie(0)可以解绑定
ifs/cin>>noskipws:读取char类型时可以读取空格(可以通过skipws恢复)
cin.sync_with_stdio(0):关闭同步,这个时候如果有print又有cout就会先把print的执行完(因为cout会先把数据存到缓冲区,而print直接把数据输出到屏幕)
endl会刷新缓存区,所以为了提升效率用'\n'即可
freopen("文件路径",“r/w”,stdin/stdout):重定向,将cin>>x的键盘输入重定向为文件读入(也可以通过cin.rdbuf(ifs.rdbuf()//文件的缓冲区)将cin的缓冲区挂靠为文件的rdbuf形成重定向)
向一个文件写东西,并且读出并写到另一个文件:
fstream ofile("file1.txt", ios::in);
ofstream ofile2("file2.txt", ios::out);
ofile << "abc\ndef";//写文件
ofile.seekg(ios::beg);//将指针重新定位文件头
ofile2 << ofile.rdbuf();//将缓冲区东西输入到第二个文件
ofile.close();
ofile2.close();输出格式化:showpos(正数显示+),showpoint(显示小数点),fixed,scientific,uppercase,left,right,dec,oct,hex等
注:cout.fill()+cout.width()或setw输出方式是右对齐
关于重载
重载[]:
int*& operator[](int i) {
return p[i];
}
重载输出运算符:friend ostream& operator<<(ostream& out, Point& p) {
out << p.x << "," << p.y;
return out;
}
. :: ?: .* sizeof不可重载
关于模板
普通函数参数为函数时:可以
void fun(int fun2(~)):~依据需求填写,可以不写变量名
void fun(int (*fun2)(~)) 函数体内直接fun2(~)即可,*无影响,当成附加的东西即可
若为模板函数则
Template
Void fun(T fun2){
fun2(~):~依据需求填即可
}
模板中
typename C::const_iterator it(container.begin()):typename用于声明C::const_iterator是类型名而不是一个变量
template
class CMyistream_iterator
{
private:
T value;
istream ∈//使用引用的目的是减少开销,避免调用构造函数等等
public:
CMyistream_iterator(istream &_in):in(_in) {//此处采用引用接受的目的是保证没有复制构造函数调用
in >> value;//读入第一个数
}
T operator *() {
return this->value;
}
void operator++(int) {
in >> value;//读入后续的数
}
};
模板实现具体化,前缀+template<>即可
template<> bool myCompare(Person& p1, Person& p2)
{
if (p1.m_Name == p2.m_Name && p1.m_Age == p2.m_Age)
{
return true;
}
else
{
return false;
}
}
类型转换
重载强制类型转换:operator int()
{
return n;
}
看某字符的ASCII码:(int)ch;
可以直接给字符赋ASCII码:char ch=97;//int 和 char 可以自动转换
static_cast<类型>(变量):类型转换(类似于C语言里的())
多态中向下转型用dynamic_cast (&a) 不要用()直接转
explicit关键字用来防止类构造函数的隐式自动转换
此时
class CxString // 使用关键字explicit的类声明, 显示转换
{
int _size;
explicit CxString(int size)
{
_size = size;
}
}
CxString string2 = 10; CxString string6 = ‘c’;就不行了因为发生不了隐式转换
关于const
const Point operator+(const Point &point) const {
return Point(m_x + point.m_x, m_y + point.m_y);
}
- Point p1 = (10, 20);
Point p2 = (20, 30);
(p1 + p2) = Point(40, 50); // 如果不加第1个const,则这里不会报错(应当让常量不能被赋值)
- Point p1 = (10, 20);
const Point p2 = (20, 30);
Point p3 = p1 + p2; // 不加第2个const,这里会报错,因为p2是常数(应当让常量也可以参与运算)
- const Point p1 = (10, 20);
Point p2 = (20, 30);
Point p3 = p1 + p2; // 不加第3个const,这里会报错,因为p1是常数(让常量可以调用函数)
Point& operator++() {} // 默认代表重载++a(a为变量)
const Point operator++(int) {} // 传入参数写int代表a++,固定格式。不能返回局部变量的引用
常量指针:const int* p=&a (常的是*,故指向可以改变,但不能*p=其他东西)
指针常量:int* const p=&a(常的是指针,故指向不可改变,但可以*p=其他东西)
常函数不可更改本类成员变量(除非有mutable修饰)
静态成员变量需要在类外初始化;
静态函数只能调用静态东西
常函数和普通函数啥都能调用
常对象只能调用静态成员函数和常成员函数
普通对象和静态对象啥函数都能调用
字符串与int、double转换
#include
atof(字符数组.c_str()):返回该字符串对应的double值,类似于java中的Double.parseDouble(字符串)
atoi(字符数组.c_str()):返回该字符串对应的int值,类似于java中的Integer.parseInt(字符串)
gcvt(double值,8(精度),字符数组):取double值8的精度存到字符数组中,类似于java中的double值+“ ”
itoa(int值,字符数组,10(进制)):取int值以10进制存到字符数组中,类似于java中的int值+“ ”
to_string(int a):int转变为string
访问权限
public
protected
private
公有继承
public
protected
不可见
私有继承
private
private
不可见
保护继承
protected
protected
不可见
子类可以调用本类对象继承来的保护性成员,但不能调用父类对象的该保护成员(只给子类看,其实例对象也不能看)
Son son
son.Father::m:继承中有同名属性想访问父类的属性时
class Base { public: virtual void fun(double) { cout << "base~"; } }; class Son : public Base { public: void fun(int) {//也有继承过来的fun,这里是非多态,因为形参不同 cout << "Son~"; } }; int main() { Son s; s.Base::fun(3.3);//若是s.fun优先调用本类的,调用父类的fun可以像这样显示声明 return 0; }virtual void fun()=0是纯虚函数,使其子类可以重写
当有virtual修饰类时,多继承时该类指向同一块区域,不需要限定访问权限(不需要d::B.a,直接d.a),解决二义性。
C语言独有
getchar()读取一个字符
gets()读取字符串
Char *a=“abc”;
十进制输出:%d
八进制输出:%o
十六进制输出:%x
字符串输出:%s
字符输出:%c
浮点形式输出:%f
C/C++中的strcpy(),strcat(),strlen(),strcmp()都是操控字符数组的
string类
string类初始化:
- const char* str=”hello”;
- string str(10,’a’):10个a构成
- string str=”hello”;
- string str;
str.assign(“hello”)
- string str;
str.assign(5,’x’)
string类方法
- +
- append
- find():返回下标
- rfind():返回最后一个下标
- replace(1,3,“abc”):将从1始3个字符换成abc
- compare():若相等返回0
- size():字符串长度
- at、[]可访问
- insert(num,”abc”):在num处插入abc
- erase(1,3):删除从1始3个字符
- substr(1,3):从1始截取3个字符
内置数据结构
vector初始化:
- vector
v2(v1.begin(),v1.end()) - vector
v(10,100):10个100 - vector
v3(v1) v.assign(v2.begin(),v2.end()):给v重定义为v2的对应位置
size实际有的元素个数(resize(n,(m))可以更新元素个数,若只有n,就是n个默认构造的东西,若还有m就是n个m。
capacity是容量,如果size>capacity就会自动扩容(reserve(n)可以手动扩容为n)。
注:
- vector对象的大小都是12个字节(两个指针(element、vptr)和int size)
- vector重载了==,判断的是内容是否相等
优先队列
struct node {//重写< int val; bool operator<(const node& a) const { return val < a.val; //大顶堆 } }; priority_queue<node> myque1; //类似于Java节点实现Comparable接口内部重写compareTo方法 struct node2 {//谓词 bool operator()(node a, node b) { return a.val < b.val; } }; priority_queue<node, vector, node2 > myque2;//内置结构谓词不需(),类似Java中new Comparetor 重写Compare方法
vector |
deque |
stack |
queue |
list |
set |
map |
|
增 |
Push_back() |
Push_back() Push_front() |
Push() |
Push() |
Push_front() Push_back() |
||
删 |
Erase() Clear() Pop_back() |
Pop_back() Pop_front() |
Pop() |
Pop() |
Clear() Erase() Pop_back() Pop_front() Remove() |
Erase() |
Erase() Clear() |
改 |
|||||||
查 |
[]、at() |
[]、at() |
|||||
大小 |
Size() |
Size() |
Size() |
Size() |
Size() |
Size() |
|
容量 |
Capacity() |
无 |
|||||
指定大小 |
Resize() |
Resize() |
Resize() |
||||
插入 |
Insert() |
Insert() |
Insert() (插入后自动排序) |
Insert() (插入后根据值自动排序) |
|||
空 |
Empty() |
Empty() |
Empty() |
Empty() |
Empty() |
Empty() |
|
头 |
Front() |
Front() |
Top() |
Front() |
Front() |
||
尾 |
Back() |
Back() |
Back() |
Back() |
|||
交换 |
Swap()(自换可收缩容量) |
Swap() |
Swap() |
Swap() |
|||
反转 |
Reverse() |
||||||
预留空间 |
Reserve() |
||||||
迭代器 |
iterator |
iterator |
iterator |
iterator |
Const_iterator |
||
备注 |
Set不允许重复插入数据,multiset可 |
Map不允许有重复key,multimap可以 |
仿函数与谓词
函数对象即仿函数是重载了()的类
若返回的是bool类型,则该仿函数也叫谓词(一个参数就一元谓词,两个参数就二元谓词)
List不可跳跃访问(即不可it=it+1;但可it++)
cout<< a(3, 4) or A()(3,4);//可以直接通过类对象()调用重载函数
for_each(a.begin(), a.end(), A() or a);//做仿函数不需要写参数,普通函数可以直接写函数名
set,map想要定制排序也可以在
设定 仿函数也可以用lambda函数实现,如[](int a,int b){return a>b;}
关于lambda
- 如上,用作仿函数
- function
f=[&(地址传递,可更改外部变量)or=(数值,不可更改or空着)](int a){} 返回类型(传入类型)一般来说auto即可,如果是用到递归就要#include并且写前面这一堆用于说明这个是函数,类似于typename
内建仿函数
- plus
- minus
- multiplies
- divides
- modulus:取模
- negate:取反
- greater
- greater_equal
- less
- less_equal
- equal_to
- not_equal_to
- logical_and
- logical_or
- logical_not
STL算法
遍历
- for_each(beg,end,fun)
- transform(beg1,end1,beg2,fun): 搬运容器到另一个容器中
查找
- find(beg,end,value):返回迭代器
- find_if(beg,end,fun):按条件找
- adjacent_find(beg,end):找相邻重复元素的第一个的迭代器
- binary_search(beg,end,value):找到返回true
- count(beg,end,value):统计个数
- count_if(beg,end,fun):根据条件统计个数
- lower_bound(beg,end,value):用二分查找的方式查找第一个>=value的数的指针
- upper_bound(beg,end,value):用二分查找的方式查找第一个>value的数的指针
排序
- sort(beg,end,fun)
- random_shuffle(beg,end):随机排序
- merge(beg1,end1,beg2,end2,destination):合并两有序容器中的元素到新容器
- reverse(beg,end):反转
拷贝、替换
- copy(beg,end,destination)
- replace(beg,end.old,new)
- replace_if(beg,end,fun,new)
- swap(container1,container2)
算数生成(包含numeric)
- accumulate(beg,end,value)
- fill(beg,end,value):填充
集合
- set_intersection(beg1,end1,beg2,end2,destination):
- 两集合元素有序
- 目标容器指定大小为min(v1,v
- 返回值是交集最后一个元素的迭代器
- set_union(beg1,end1,beg2,end2,destination)
- 两集合元素有序
- 目标容器指定大小为size(v1)+size(v
- 返回指是并集最后一个元素的迭代器
- set_difference(beg1,end1,beg2,end2,destination)
- 两集合元素有序
- 目标容器指定大小为max(v1,v2)
- 返回值是差集最后一个元素的迭代器