1、什么是拷贝构造函数
2、什么情况下调用拷贝构造函数?
- 对象声明的时候就初始化(赋值)
public class Student{
private:
char*name;
int id;
};
Student a;
Student b=a;//拷贝
- 以值作为参数传递
void f(Student a)//调用这个函数的时候,会调用拷贝构造函数
- 以值作为返回值传递
Student f(Student a){
return a;
}
3、浅拷贝和深拷贝的区别?
4、浅拷贝和深拷贝各有什么特点
浅拷贝对于在栈上面的数据进行拷贝是非常好的,而且效率也是非常高的。比如上面的b.id=a.id,这个就是在栈上面的拷贝,
对于在堆上面的拷贝就有点显得不足了,因为在一个对象的生面周期结束的时候,会调用析构函数,而我们会在析构函数里面释放内存(在堆上面分配的)
如果是浅拷贝,先释放a这个对象的时候,我们会把a.name所指的内存释放,此时b.name指的区域就是无效的,等析构b对象的时候,
我们释放b.name所指的内存就会报错,因为那块区域是无效的了,释放无效内存是会报错的。
深拷贝就会解决这个问题,因为a.name和b.name所指的内存是不同的。
拷贝构造函数的一般写法
Student::Student(const Student&student){
int length=strlen(student.name)+1;
this->name=new char[length+1];//这里就是深拷贝,先在堆上面分配内存,然后拷贝内容
strcpy(this->name,student.name);
}
5、什么是赋值操作
对象在申明之后,在进行的赋值运算,我们称之为赋值运算,比如说:
Student a; Student b;//声明两个对象
a=b;//赋值操作
赋值操作的一般写法
Student& Student::operator=(const Student& student){
if(this==&student){
return *this;//遇到a=a这个种情况
}
if(this->name!=NULL){
delete []name;//释放之前的在堆里面分配的内存
}
int length=strlen(student.name)+1;
this->name=new char[length];
strcpy(this->name,student.name);
this->id=student.id;
return *this;
}
6、比较拷贝构造函数和赋值操作
1、传递参数的形式:都是用传引用的方式,(拷贝构造函数是用引用,详情请点击这里)
2、拷贝构造函数无须释放this->name的内存,这是因为当前对象还没有建立,而赋值操作要释放this->name的内存,那是因为这个对象已经存在于内存上面了。
3、由于调用赋值操作的时候,对象都是建立的了,所以在赋值的时候,我们就检验是否为自己赋值给自己,这样就避免浪费内存。
3、赋值操作返回的是引用,为什么不是值传递或者是指针传递(详情点击这里)