拷贝构造函数
功能: 使用一个已经存在的对象来初始化一个新的同一类型的对象。 声明: 只有一个参数并且参数为该类对象的引用 如果类中没有说明拷贝构造函数,则系统会自动生成一个缺省复制构造函数,作为该类的公有成员。
当函数的形参是类的对象,调用函数时,进行形参与实参结合时便用。 这时要在内存新建立一个局部对象,并把实参拷贝到新的对象中。理所当然也调用拷贝构造函数。
代码语言:javascript复制 1 #include"copy.h"
2 /*void function(const person& p)
3 {
4 cout<<"constructor"<<endl;
5 }*/
6 void function2(const person p)
7 {
8 cout<<"constructor"<<endl;
9 }
10
11 int main()
12 {
13 person p(10,20);
14 person pp(p);
15 person ppp = pp;
16
17 function2(p);
18 return 0;
19 }
结果:
代码语言:javascript复制[bsk@localhost structor]$ ./a.out
person constructor //p的默认构造调用
copy function10 //pp的拷贝构造调用
copy function10 //ppp的拷贝构造调用
copy function10 //function函数拷贝构造
constructor
那如果函数参数时以引用的方式,会不会调用拷贝构造函数呢?
代码语言:javascript复制 1 #include"copy.h"
2 void function(const person& p)
3 {
4 cout<<"constructor"<<endl;
5 }
6 int main()
7 {
8 person p(10,20);
9 person pp(p);
10 person ppp = pp;
11
12 function(p);
13 return 0;
14 }
结果如下:
代码语言:javascript复制[bsk@localhost structor]$ ./a.out
person constructor //p的默认构造调用
copy function10 //pp的拷贝构造调用
copy function10 //ppp的拷贝构造调用
constructor //function函数调用
当函数的返回值是类对象,函数执行完成返回调用者时使用。理由也是要建立一个临时对象中,再返回调用者。
代码语言:javascript复制#include"copy.h"
person function3(const person& p)
{
return p;
}
int main()
{
person p(10,20);
function3(p);
return 0;
}
结果:
代码语言:javascript复制[bsk@localhost structor]$ ./a.out
person constructor //p的默认构造
copy function10 //function 在返回类对象时调用的拷贝构造
为什么不直接用要返回的局部对象呢?因为局部对象在离开建立它的函数时就消亡了,不可能在返回调用函数后维续生存,所以在处理这种情况时,编译系统会在调用函数的表达式中创建一个无名临时对象,该临时对象的生存周期只在函数调用处的表达式中。如果用一个新变量来接收临时对象, 临时对象变成有名对象,则此对象就不会马上销毁
所谐return对象,实际上是调用拷贝构造函数把该对象的值拷入临时对象。如果返回的是变量,处理过程类似,只是不调用构造函数
代码语言:javascript复制#include"copy.h"
const person& function3(const person& p)
{
return p;
}
int main()
{
person p(10,20);
person pp = function3(p);
const person & ppp= function(p);//因为引用,共用一块内存空间,不会调用拷贝构造函数
return 0;
}
结果:
代码语言:javascript复制[bsk@localhost structor]$ ./a.out
person constructor //p的默认构造
copy function10 // pp = function3(p);拷贝构造
深浅拷贝
深拷贝指的是在进行对象复制时,不仅复制了对象本身,还复制了对象所引用的其他对象,以确保复制后的对象与原始对象完全独立,彼此之间不会相互影响。换句话说,深拷贝会递归地复制对象及其所有引用的对象,从而创建一份全新的、独立的副本。
举个例子,假设有一个包含其他对象引用的复杂对象A,通过深拷贝后得到的副本B将会包含与A中相同类型和值的所有对象,而不是简单地复制它们的引用。这意味着对副本B的任何修改都不会影响原始对象A,因为它们引用的是完全独立的对象。
在编程中,实现深拷贝通常需要递归遍历对象结构,并对其中的每个对象进行复制。对于复杂的数据结构,如嵌套的列表、字典或自定义对象,确保进行深拷贝尤为重要。
深拷贝能够确保对象复制的完整性和独立性,但也需要额外的系统资源来完成复制操作。因此,在进行对象复制时,需要权衡资源消耗和需求,选择适合的复制方式。
代码语言:javascript复制#include<iostream>
using namespace std;
class person
{
public:
person()
{
cout << "person()的默认构造" << endl;
}
person(int age,int hight)
{
myage = age;
myheight =new int( hight);
cout << "person()的有参函数构造" << endl;
}
//shenkaobei
person(const person& p)
{
myage = p.myage;
//myheight = p.myheight;编译器默认(浅拷贝)提供的
//因为是指针地址,会导致两个名释放同一块内存空间
//深拷贝
myheight = new int(*p.myheight);
}
~person()
{
//析构函数将,堆区 ,开辟的数据进行释放
if (myheight != NULL)
{
delete myheight;
myheight = NULL;
}
cout << "person()的析构函数构造" << endl;
}
int myage;
int* myheight;
};
void test01()
{
person p1(10,120);
person p2(p1);
cout << p2.myage<<endl <<*p2.myheight<< endl;
return;
}
int main()
{
test01();
system("pause");
return 0;
}