C++学习笔记

C++学习笔记,第1张

一、一些重要的常见知识点
1.函数的分文件编写:

.h的头文件(写函数声明)  .cpp的源文件(写函数功能实现)


2.空指针和野指针 : 

0-255的内存是系统所占有的      `int *p=(int *)0x1001` //是一种错误


3.常量指针:

`const int *p=&a` //a不可以改变,p可以改变


4.指针常量:

`int * const p=&a ` //a可以改变,p不可以改变


5.结构体数组:

 `struct student arr[3]{}`


6.函数形参用const修饰,可防止在函数中对实参误 *** 作
7.堆区的开辟和释放:new和delete 
int *p=new int(6);
delete p;  
int *q=new int[6];  
delete[] q;                //数组delete要加[]
8.引用:

  给变量取别名

int a=6;
int &b=a;  //a和b同时指向6所在地址空间


  引用必须初始化,且初始化后不可更改
  函数返回值不可以是 局部变量 、引用类数据,  可以用static全局变量引用类数据
  引用本质是一个指针常量
  常量引用:用来修饰形参,防止误 *** 作

9.函数中的默认参数:


函数形参可以有默认值,若调用传入自己的值,则用传入的值,否则用默认值

从第一个有默认值的形参开始,后面所有的参数都要有默认值 

函数声明中有默认值后,函数实现里不可以有默认值参数

10.函数重载:

1.遇到常量引用时   2.遇到默认参数值时

 二、类和对象
1.类中成员的访问权限:


 public  protected  private
struct默认权限是公共,class默认权限是私有

2.构造函数和析构函数:


构造函数语法:类名(){函数体}  

析构函数语法:~类名(){函数体}


普通构造函数
拷贝构造函数:`Person(const Person &p){ name=p.name; }`


  调用拷贝构造函数的三种情况:

1.使用一个创建完成的对象创建一个新的对象  

2.值传递的方式给函数参数传值(形参是一个对象值时,实参传入时会拷贝一个副本,即创建一个新的对象,使用拷贝构造函数)  

3.以值方式返回局部对象(函数返回类型是一个类,在调用这个函数,将该函数返回值赋值给另一个对象时,会创建一个新的对象,使用拷贝构造函数)


匿名对象: `Person();`匿名对象被创建后会被系统立刻回收

编译器提供的默认函数: 默认无参构造函数、析构函数、拷贝构造函数
规则:若定义有参构造,则不提供默认无参构造,但提供拷贝构造  若定义拷贝构造,则不提供其他构造

3.浅拷贝与深拷贝


浅拷贝:简单的等号赋值  

深拷贝:另外开辟一块空间进行拷贝赋值


创建对象时若有申请空间,使用完后需释放堆区空间,在使用拷贝构造时,若使用浅拷贝,则会有重复释放的问题,此时需要用深拷贝(在析构函数中释放)

4.初始化列表:
 Person(int a,int b,int c):pA(a),pB(b),pC(c){}


初始化类的成员有两种方式,一是使用初始化列表,二是在构造函数体内进行赋值 *** 作


必须使用初始化的几种情况:
常量成员: 因为常量只能初始化不能赋值,所以必须放在初始化列表里面
引用类型: 引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面
没有默认构造函数的类类型: 因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化。

5.类对象作为另一个类的成员: 

创建时先构造成员对象,析构时先析构本类

6.static关键字: 

1.所有对象共享 2.编译阶段分配内存 3.类内声明,类外初始化 

class Person{
public: 
    static int age;
} 
int Person::age=3;        //类外初始化


静态成员函数:只能访问静态成员变量


一个空对象占用一个字节内存(每个空对象都应有一个独一无二的地址空间)
只有非静态成员变量才属于类的对象(成员变量和成员函数分开存放)

7.this关键字:

1.解决名称冲突

2.返回对象本身用*this (this指向被调用函数所属的对象)

8.const关键字:

 在成员函数后加const(常函数),修饰的是this指向,函数内部this所指向的值不可被修改(可加mutable使仍可以修改)


常对象:只可以调用常函数

9.友元: 

全局函数/类/其他类的成员函数前加friend关键字(写进类中),则该函数可以访问类中的private变量

10.运算符重载:
class person{
public:
    int a;
    int b;
} 


加运算符重载方法:

 //1.成员函数重载 
person operator+(person &p){          //在类内
person tmp; 
tmp.a=this.a+p->a; 
tmp.b=this.b+p->b; 
return tmp;
} 
//2.全局函数重载
person operator+(person &p1,person &p2){        //在类外
person tmp; 
tmp.a=p1->a+p2->a; 
tmp.b=p1->b+p2->b; 
return tmp; 
}
//这些重载函数可以函数重载,即函数参数类型可以改变

左移运算符重载:

//只能用全局函数实现
ostream & operator<<(ostream &cout,person &p){ 
    cout<


++运算符重载: 

//成员函数实现  前置++:
myinteger& operator++(){            //返回类型为指针
    num++; 
    return *this;
}    
//后置++: 
myinteger operator++(int){        //int 为占位参数, 返回类型为值而不是指针,因为tmp是个局部对象
    myinteger tmp=*this; 
    num++; 
    return tmp;
}  
11.继承: 

语法:

class 子类 : 继承方式 父类


继承方式:公共继承、保护继承、私有继承
父类的非静态成员属性都会被子类继承

子类父类构造和析构的顺序


继承中父类和子类同名时的访问问题:访问父类时要加作用域,如果子类中有和父类重名的成员函数,子类的同名函数会隐藏掉所有的父类同名函数


菱形继承,要用virtual虚继承解决,父类继承基类时加virtual

12.静态多态/动态多态


动态:父类中的函数写为virtual虚函数,子类重写该虚函数

纯虚函数:

virtual 返回值类型 函数名 (参数)=0;

当类中有了纯虚函数,这个类也叫作抽象类


虚析构/纯虚析构:

解决父类指针释放子类对象问题(父类指针指向子类对象若无虚析构,析构时不会调用子类的析构函数,而只会析构父类)   用virtual修饰父类的析构函数

 三、文件 *** 作:


头文件:  
三大文件 *** 作类型:写:ofstream  读:ifstream  读写:fstream
 文件打开方式:ios::in  ; ios::out  ; ios::binary


 例子:写文件:

ofstream ofs; ofs.open(“文件名”,打开方式); 
ofs<<"xiewenjian<

 四、模板:

语法:

   template  void myswap(T &a,T &b){}


 使用方式:
 1.自动类型推导 `myswap(1,2);`  不会发生隐式类型转换  或:
 2.显示指定类型 'myswap(1,2);` 可以进行隐式类型转换(和普通函数一样)
 模板必须要确定T的数据类型才可以使用
 ps:隐式类型转换举例:int和其他类型数据运算,其他类型隐式转换为int


 模板和普通函数的调用规则:

1.普通函数和模板都可调用时,优先普通函数

2.可使用空参数列表模板强制调用模板`myswap<>(1,2);`

3.模板也可以重载

4.如果模板更好的匹配,优先模板 模板具有局限性,可以用函数模板重载方法,将模板参数具体化,会优先调用参数具体化的模板 

template <> bool mycompare(person &p1,person &p2){};


类模板:

template   class person{ 
person(nametype name,agetype age){} 
}  
person p("yxh",2);


 1.类模板没有自动类型推导  

2.类模板参数列表可以有默认参数

  template 


 普通类的成员函数一开始就可以被创建(定义时) 类模板的成员函数只有在调用时才会被创建

类模板作函数参数三种方式:


1.指定参数类型

void printperson( person{} ) 


2.参数模板化

template  void printperson(person){}   
//查看某个类型的名字:`typeid(nametype).name()`  


3.整个参数模板化

template  void printperson(T &p){}

类模板与继承:

如果父类是类模板,子类需要指定父类的T的类型,或者,子类也成为一个类模板

类模板成员函数类外实现:

template 
person::person(nametype name,agetype age){}

类模板分文件编写:

由于类模板的成员函数是在调用时才创建,只包含头文件h而不包含源文件cpp时,不 可行,解决办法:1.直接包含cpp文件,2.将h和cpp内容写到一起,命名为hpp文件,包含hpp文件

五、stl(标准模板库):


stl广义上分为:容器(序列式容器、关联式容器)、算法(质变算法、非质变算法)、迭代器  //(还有仿函数、适配器、空间配置器)

容器和算法通过迭代器链接,每个容器都有自己的迭代器,算法通过迭代器访问容器中的数据

1.string容器:


string字符串拼接:

string& operator+=(const char* str); 
string& operator+=(const char ch); 
string& operator+=(const string& str);  
string& append(const char* str); 
string& append(const char* str,int n); 
string& append(const string &str); 
string& append(const string &str,int pos,int n);


string字符串查找:

int find(const string& str,int pos);  
int find(const char* str,int pos);  
int find(const char* str,int pos,int n);  
int find(char c,int pos); //查找第一个位置,rfind用于查找最后一个位置


string字符串替换:

string& replace(int pos,int n,const string& str); 
string& replace(int pos,int n,const char* str);


string字符串比较:

int compare(const string& str);  
int compare(const char* str);


string字符串获取:

char& at(int n);


string字符串插入:

string& insert(int pos,const char* str);  
string& insert(int pos,const string& str);  
string& insert(int pos,int n,char c);


string字符串删除:

string& erase(int pos,int n);


string获取子串:

string& substr(int pos,int n);
2.vector容器


vector构造函数:

vector v;  
vector(v1.begin(),v1.end());  
vector(n,elem);  
vector(const vector &v1);


vector赋值 *** 作:

assign(v1.begin(),v1.end());  
assign(int n,elem e);


vector容量 *** 作:

v.empty();  
v.size(); 
v.capacity();  
v.resize(int n);  
v.resize(int n,elem e);


vector通过迭代器删除:

v.insert(const_iterator pos,elem e);  
v.insert(const_iterator pos,int num,elem e);  
v.erase(const_iterator pos);  
v.erase(const_iterator begin,const_iterator end); 
v.clear();


vector取数据:

v.front();
v.back();


vector交换两个容器的数据:

v.swap(v1) 
vector(v).swap(v);    //可利用swap和匿名对象减小空间浪费 
//vector预留空间:
reserve(int n)          //预留位置不初始化不可访问
3.deque容器


deque: vector单端数组,deque双端数组,vector头部插入删除效率低,deque访问速度慢,deque无capacity接口,没有容量概念
deque排序:`sort(begin(),end());` //sort算法,对于支持随机访问的迭代器的容器,都可以用sort排序

4.list容器


list:迭代器不支持随机访问,是一个双向迭代器,也不可用[]和at访问元素
 翻转:reverse()、排序sort()  //两个都是成员函数

5.set和multiset:


 特点:插入时会自动排序,属于关联式容器,底层结构是二叉树,set不允许有重复元素,multiset允许
  删除的重载:erase(elem e); 
  查找:find(elem e);//若存在,则返回该元素的迭代器,否则返回end()    
  统计:count(elem e); 
   插入只有insert();
  set内置数据类型时有默认排序规则,也可通过仿函数修改规则,但自定义类型必须先指定排序规则,否则无法插入   

6.pair:


pair对组:成对出现的数据,利用对组可以返回两个数据
 创建方式:

pair p(value1,value2);  
pair p=make_pair(value1,value2) 
//利用first和second取数据
7.map/multimap:


 map中所有元素为pair类型,pair第一个数据为key值,起索引作用,第二个为value值,所有元素按照key值自动排序,属于关联式容器,底层结构是二叉树

map m; 
m.insert(pair)(type1value,type2value)) m.insert(make_pair(type1value,type2value)) 
//可用[]访问元素:m[key]=value
六、函数对象:


重载函数调用符()的类,其对象称为函数对象
 函数对象在使用时,可以像普通函数那样,有参数,有返回值
 函数对象可以有自己的状态,可以作为参数进行传递
返回bool类型的仿函数称为:谓词

 七、常见算法合集


搬运算法:transform(v1.begin,v1.end,v.begin)  //搬运前需要开辟空间
遍历算法:for_each(v1.begin,v1.end,fun)

常用查找算法:find、find_if、adjacent_find、binary_search、count、count_if

常用排序算法:sort、random_shuffle、merge、reverse

常用拷贝和替换算法:copy、replace、replace_if、swap

常用算术生成算法:fill、accumulate  //include

常用集合算法:set_intersection、set_uniom、set_difference

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/2991824.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-23
下一篇 2022-09-23

发表评论

登录后才能评论

评论列表(0条)