类的实例化:
构造函数/析构函数:
1.默认构造函数
2.有参构造函数
3.拷贝构造函数
4.移动构造函数
4.析构函数
没有返回值
使用初始化列表初始化可以节省cpu的消耗,效率高
分配内存->匹配构造函数->初始化列表初始化->进入大括号才能类对象还未构造完成(此时才能用this指针)
delete->调析构函数->执行析构函数体->释放内存
int n=1;
int m(1);
C++11的写法int k{1};都是调用构造函数
int类型的可以隐式转换成double型,但float不能转为int
如果自己定义有参构造函数,此时编译器不在进行默认构造函数
People(const People &p) 拷贝构造函数必须使用引用传递
若为People(const People p)值拷贝,这里会为p创建一个临时的拷贝,此时会不断调用拷贝构造函数陷入死循环
malloc/free 分配内存和释放内存
new/delete: 分配内存(调用构造函数,重载操作符)和释放内存(调用析构函数)
#define new new(__FILE__,__LINE__)
void*operator new(size_t size,char*file,long line){
//cout<<"operator new"<<size<<__FILE__<<__LINE__<<endl;
cout<<"operator new"<<size<<file<<line<<endl;
void *p=malloc(size);
return p;
}
const int size=1024;
char*buff=new char[size];
void*operator new(size_t size,void*ptr){
cout<<"operator placement new"<<endl;
return ptr;
}
People*p1=new (buff)People("master2",18,60,120);
p1->~People();//这里需要显示地调用析构函数
delete buff;//谁调用谁释放,这里不能用p1;
void*operator delete(void*ptr){
cout<<"operator delete"<<endl;
if(ptr) free(ptr);
}
=delete 取消某种构造函数//设计模式用到
=default 使用系统默认地构造函数
浅拷贝和深拷贝:
#include<iostream>
using namespace std;
class Point{
private:
float _x,_y;
public:
Point(float x,float y):_x(x),_y(y){
}
};
class Line{
private:
Point*start;
Point*end;
public:
Line():start(nullptr),end(nullptr){
}
Line(const Point&p1,const Point&p2)
:start(new Point(p1)),end(new Point(p2)){
}
// Line(const Line& line):start(line.start),end(line.end){
// //浅拷贝的方式
// }
Line(const Line& line):start(new Point(line.start)),end(new Point(line.end)){
// //深拷贝的方式
// }
~Line(){
delete start;
delete end;
}
}
int main(){
Point*p1=new Point(1.0f,2.0f);
Point*p2=new Point(2.f,3.0f);
Line*line1=new Line(*p1,*p2);
Line*line2=new Line(*line1);
delete line2;
delete line1;
delete p2;
delete p1;
return 0;
}
//深拷贝需重载复制函数
void operator=(const Line&line){
if(line.start){
if(start){
memcpy(start,line.start,sizeof(Point));
}else{
start=new Point(*line.start);
}
}else{
if(start) delete start;
start=nullptr;
}
if(line.end){
if(end){
memcpy(end,line.end,sizeof(Point));
}else{
start=new Point(*line.end);
}
}else{
if(end) delete end;
end=nullptr;
}
}
三五法则:
- 需要析构函数的类也需要拷贝构造函数和拷贝赋值函数。
- 需要拷贝操作的类也需要赋值操作,反之亦然。
- 析构函数不能是删除的
- 如果一个类有删除的或不可访问的析构函数,那么其默认和拷贝构造函数会被定义为删除的。
- 如果一个类有const或引用成员,则不能使用合成的拷贝赋值操作。