对于拷贝构造函数以及赋值构造函数的定义
- 格式:pdf
- 大小:75.96 KB
- 文档页数:2
详解C++中构造函数,拷贝构造函数和赋值函数的区别和实现C++中⼀般创建对象,拷贝或赋值的⽅式有构造函数,拷贝构造函数,赋值函数这三种⽅法。
下⾯就详细⽐较下三者之间的区别以及它们的具体实现1.构造函数构造函数是⼀种特殊的类成员函数,是当创建⼀个类的对象时,它被调⽤来对类的数据成员进⾏初始化和分配内存。
(构造函数的命名必须和类名完全相同)⾸先说⼀下⼀个C++的空类,编译器会加⼊哪些默认的成员函数默认构造函数和拷贝构造函数析构函数赋值函数(赋值运算符)取值函数**即使程序没定义任何成员,编译器也会插⼊以上的函数!注意:构造函数可以被重载,可以多个,可以带参数;析构函数只有⼀个,不能被重载,不带参数⽽默认构造函数没有参数,它什么也不做。
当没有重载⽆参构造函数时,A a就是通过默认构造函数来创建⼀个对象下⾯代码为构造函数重载的实现<span style="font-size:14px;">class A{int m_i;Public:A(){Cout<<”⽆参构造函数”<<endl;}A(int i):m_i(i) {} //初始化列表}</span>2.拷贝构造函数拷贝构造函数是C++独有的,它是⼀种特殊的构造函数,⽤基于同⼀类的⼀个对象构造和初始化另⼀个对象。
当没有重载拷贝构造函数时,通过默认拷贝构造函数来创建⼀个对象A a;A b(a);A b=a; 都是拷贝构造函数来创建对象b强调:这⾥b对象是不存在的,是⽤a 对象来构造和初始化b的!!先说下什么时候拷贝构造函数会被调⽤:在C++中,3种对象需要复制,此时拷贝构造函数会被调⽤1. 1)⼀个对象以值传递的⽅式传⼊函数体2. 2)⼀个对象以值传递的⽅式从函数返回3. 3)⼀个对象需要通过另⼀个对象进⾏初始化什么时候编译器会⽣成默认的拷贝构造函数:1. 1)如果⽤户没有⾃定义拷贝构造函数,并且在代码中使⽤到了拷贝构造函数,编译器就会⽣成默认的拷贝构造函数。
C++拷贝(复制)构造函数详解⼀. 什么是拷贝构造函数⾸先对于普通类型的对象来说,它们之间的复制是很简单的,例如:[c-sharp]1. int a = 100;2. int b = a;⽽类对象与普通对象不同,类对象内部结构⼀般较为复杂,存在各种成员变量。
下⾯看⼀个类对象拷贝的简单例⼦。
[c-sharp]1. #include <iostream>2. using namespace std;3.4. class CExample {5. private:6. int a;7. public:8. //构造函数9. CExample(int b)10. { a = b;}11.12. //⼀般函数13. void Show ()14. {15. cout<<a<<endl;16. }17. };18.19. int main()20. {21. CExample A(100);22. CExample B = A; //注意这⾥的对象初始化要调⽤拷贝构造函数,⽽⾮赋值23. B.Show ();24. return 0;25. }运⾏程序,屏幕输出100。
从以上代码的运⾏结果可以看出,系统为对象 B 分配了内存并完成了与对象 A 的复制过程。
就类对象⽽⾔,相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。
下⾯举例说明拷贝构造函数的⼯作过程。
[c-sharp]1. #include <iostream>2. using namespace std;3.4. class CExample {5. private:6. int a;7. public:8. //构造函数9. CExample(int b)10. { a = b;}11.12. //拷贝构造函数13. CExample(const CExample& C)14. {15. a = C.a;16. }17.18. //⼀般函数19. void Show ()20. {21. cout<<a<<endl;22. }23. };24.25. int main()26. {27. CExample A(100);28. CExample B = A; // CExample B(A); 也是⼀样的29. B.Show ();30. return 0;31. }CExample(const CExample& C) 就是我们⾃定义的拷贝构造函数。
拷贝构造和拷贝赋值拷贝构造和拷贝赋值是面向对象编程中常用的两个概念。
它们在C++、Java等编程语言中经常被用到,对于理解对象的复制和拷贝有着重要的作用。
拷贝构造是指通过已存在的对象创建一个新的对象,这个新对象和原对象的成员变量具有相同的值。
例如,我们有一个学生类(Student),其中包含学生的姓名、学号、年龄等成员变量。
当我们通过已存在的学生对象创建一个新的学生对象时,就需要使用拷贝构造。
拷贝构造函数在C++中常用的格式为:类名(const 类名& obj)。
在拷贝构造函数中,我们将传递进来的对象的成员变量值赋值给新创建的对象的成员变量。
拷贝构造函数的使用可以大大简化对象的创建过程,并且保证了新创建的对象和原对象之间的数据一致性。
同时,拷贝构造函数还可以用于对象作为函数参数进行传递,以及对象作为函数返回值返回的情况。
拷贝赋值是指将一个已存在的对象的值赋给另一个已经存在的对象。
在C++中,我们可以通过重载赋值操作符(=)来实现对象的拷贝赋值。
拷贝赋值的格式为:类名& operator=(const 类名& obj)。
在拷贝赋值中,我们将被赋值对象的成员变量值赋给目标对象的成员变量。
拷贝赋值操作符的使用可以方便地将一个对象的值拷贝给另一个对象,使得两个对象具有相同的值。
拷贝赋值操作符还可以用于链式赋值,即多个赋值操作符连续使用的情况。
无论是拷贝构造还是拷贝赋值,都是对象间的复制操作,但它们的触发时机和方式是不同的。
拷贝构造是在创建新对象时调用,而拷贝赋值是在已有对象进行赋值操作时调用。
需要注意的是,在使用拷贝构造和拷贝赋值的过程中,我们需要自行管理动态分配的资源(如堆内存),防止内存泄漏和悬垂指针的问题。
拷贝构造和拷贝赋值在实际的编程中有着广泛的应用。
它们不仅可以用于类的对象,还可以用于容器类、智能指针等等。
对于理解对象的复制、赋值和传递过程,以及保证程序的正确性和高效性,拷贝构造和拷贝赋值具有重要的指导意义。
C++拷贝构造函数和赋值构造函数转⾃:⼀、拷贝构造函数int main(int argc, char * argv[]){CExample A;A.Init40);CExample B=A; //把B初始化为A的副本...}B = A ; 此语句的具体过程:⾸先建⽴对象theObjtwo,并调⽤其构造函数,然后成员被拷贝。
语句"CExample B=A;" ⽤ A 初始化 B。
其完成⽅式是内存拷贝,复制所有成员的值。
完成后,A.pBuffer = B.pBuffer, 即它们将指向同样的地⽅,指针虽然复制了,但所指向的空间并没有复制,⽽是由两个对象共⽤了。
这样不符合要求,对象之间不独⽴了,并为空间的删除带来隐患。
所以需要采⽤必要的⼿段(拷贝构造函数)来避免此类情况。
拷贝构造函数的格式为 : 构造函数名(对象的引⽤) 提供了拷贝构造函数后的CExample类定义为:class CExample{public :CExample(){pBuffer=NULL; nSize=0;} //构造函数~CExample(){delete pBuffer;} // 析构函数CExample(const CExample&); //拷贝构造函数void Init(int n){ pBuffer=new char [n]; nSize=n;}private :char *pBuffer; //类的对象中包含指针,指向动态分配的内存资源int nSize;};//拷贝构造函数的定义CExample::CExample(const CExample& RightSides){nSize=RightSides.nSize; //复制常规成员pBuffer=new char [nSize]; //复制指针指向的内容memcpy(pBuffer,RightSides.pBuffer,nSize*sizeof (char ));}这样,定义新对象,并⽤已有对象初始化新对象时,即执⾏语句“CExample B=A; ” 时,CExample(const CExample& RightSides)将被调⽤,⽽已有对象⽤别名RightSides传给构造函数,以⽤来作复制。
拷贝构造函数和赋值函数拷贝构造函数和赋值函数是C++中两个重要的函数,它们都是用来复制对象的。
拷贝构造函数用于创建一个新对象并将其初始化为另一个对象的副本,而赋值函数则用于将一个对象的值赋给另一个对象。
在本文中,我们将详细讨论这两个函数的作用和使用方法。
一、拷贝构造函数拷贝构造函数是一个特殊的构造函数,它用于创建一个新对象并将其初始化为另一个对象的副本。
当我们使用一个对象来初始化另一个对象时,拷贝构造函数就会被调用。
例如:```class MyClass {public:MyClass(); // 默认构造函数MyClass(const MyClass& other); // 拷贝构造函数// ...};MyClass obj1; // 调用默认构造函数MyClass obj2(obj1); // 调用拷贝构造函数```在上面的代码中,当我们使用obj1来初始化obj2时,拷贝构造函数就会被调用。
拷贝构造函数的参数是一个常量引用,它表示要复制的对象。
在拷贝构造函数中,我们可以使用另一个对象的数据来初始化新对象的数据成员,从而创建一个新的对象。
需要注意的是,如果我们没有定义拷贝构造函数,编译器会自动生成一个默认的拷贝构造函数。
这个默认的拷贝构造函数会将一个对象的数据成员逐个复制到另一个对象中。
但是,如果我们的类中有指针类型的数据成员,那么默认的拷贝构造函数可能会出现问题,因为它只是简单地复制指针的值,而不是复制指针所指向的对象。
这时,我们就需要自己定义拷贝构造函数来保证正确的复制。
二、赋值函数赋值函数是用于将一个对象的值赋给另一个对象的函数。
当我们使用一个对象来赋值给另一个对象时,赋值函数就会被调用。
例如:```class MyClass {public:MyClass& operator=(const MyClass& other); // 赋值函数// ...};MyClass obj1, obj2;obj2 = obj1; // 调用赋值函数```在上面的代码中,当我们将obj1赋值给obj2时,赋值函数就会被调用。
【C++Primer第15章】定义派⽣类拷贝构造函数、赋值运算符学习资料••定义拷贝构造函数【注意】对派⽣类进⾏拷贝构造时,如果想让基类的成员也同时拷贝,就⼀定要在派⽣类拷贝构造函数初始化列表中显⽰调⽤基类拷贝构造函数(当然在函数体内将基类部分的值拷贝也是可以的,只不过它是先⽤默认构造函数初始化后再修改的基类成员变量的值,效率⽐较低),否则它会调⽤基类的默认构造函数,⽽不会对基类的成员变量拷贝值,这样⽣成的对象,它的派⽣类部分和被拷贝的对象派⽣类部分⼀样,⽽基类部分则是默认构造函数的初始化结果。
代码例⼦1:1 #include <iostream>2using namespace std;34class A5 {6public:7 A() { cout << "A default constructor" << endl; }8 A(A&) { cout << "A copy constructor" << endl; }9 };10class B : public A11 {12public:13 B() { cout << "A default constructor" << endl; }14 B(B &b) { cout << "B copy constructor" << endl; }15 };1617int main()18 {19 B b;20 B c = b;21return0;22 }输出结果:代码例⼦2:1 #include <iostream>2using namespace std;34class A5 {6public:7 A() { cout << "A default constructor" << endl; }8 A(A&) { cout << "A copy constructor" << endl; }9 };10class B : public A11 {12public:13 B() { cout << "A default constructor" << endl; }14 B(B &b) : A(b) { cout << "B copy constructor" << endl; }15 };1619 B b;20 B c = b;21return0;22 }输出结果:C++ 基类构造函数带参数的继承⽅式及派⽣类的初始化在定义类的时候,会遇到基类的构造函数带参数,⽽⼦类⼦类构造函数不带参数,这时候如果以代码 a 的⽅式建⽴派⽣类则会出错。
C++类构造函数、拷贝构造函数、复制构造函数、复制构造函数、构造函数显⽰调⽤和隐式调⽤⼀、构造函数是⼲什么的1.class Counter2.{3.public:4.// 类Counter的构造函数5.// 特点:以类名作为函数名,⽆返回类型6.Counter()7.{8.m_value = 0;9.}10.private:11.// 数据成员12.int m_value;13.}该类对象被创建时,编译系统对象分配内存空间,并⾃动调⽤该构造函数->由构造函数完成成员的初始化⼯作eg: Counter c1;编译系统为对象c1的每个数据成员(m_value)分配内存空间,并调⽤构造函数Counter( )⾃动地初始化对象c1的m_value值设置为0故:构造函数的作⽤:初始化对象的数据成员。
⼆、构造函数的种类1.class Complex2.{3.private :4.double m_real;5.double m_imag;6.public:7.Complex() //⼀般构造函数8.{9.m_real = 0.0;10.m_imag = 0.0;11.}12.13.Complex(double real, double imag) //⼀般构造函数14.{15.m_real = real;16.m_imag = imag;17.}18.19.Complex(const Complex & c) //拷贝构造函数20.{21.// 将对象c中的数据成员值复制过来22.m_real = c.m_real;23.m_imag = c.m_imag;24.}25.Complex &operator=( const Complex &rhs ) //赋值构造函数26.{27.// ⾸先检测等号右边的是否就是左边的对象本⾝,若是本对象本⾝,则直接返回28.if ( this == &rhs )29.{30.return *this;31.}32.// 复制等号右边的成员到左边的对象中33.this->m_real = rhs.m_real;34.this->m_imag = rhs.m_imag;35.// 把等号左边的对象再次传出36.return *this;37.}38.};// ⽆参数构造函数// 如果创建⼀个类你没有写任何构造函数,则系统会⾃动⽣成默认的⽆参构造函数,函数为空,什么都不做// 只要你写了⼀个下⾯的某⼀种构造函数,系统就不会再⾃动⽣成这样⼀个默认的构造函数,如果希望有⼀个这样的⽆参构造函数,则需要⾃⼰显⽰地写出来// ⼀般构造函数(也称重载构造函数)// ⼀般构造函数可以有各种参数形式,⼀个类可以有多个⼀般构造函数,前提是参数的个数或者类型不同(基于c++的重载函数原理) // 例如:你还可以写⼀个 Complex( int num)的构造函数出来// 创建对象时根据传⼊的参数不同调⽤不同的构造函数// 复制构造函数(也称为拷贝构造函数)// 复制构造函数参数为类对象本⾝的引⽤,⽤于根据⼀个已存在的对象复制出⼀个新的该类的对象,⼀般在函数中会将已存在对象的数据成员的值复制⼀份到新创建的对象中// 若没有显⽰的写复制构造函数,则系统会默认创建⼀个复制构造函数,但当类中有指针成员时,由系统默认创建该复制构造函数会存在风险,具体原因请查询有关 “浅拷贝” 、“深拷贝”的⽂章论述// 类型转换构造函数,根据⼀个指定的类型的对象创建⼀个本类的对象,//需要注意的⼀点是,这个其实就是⼀般的构造函数,但是对于出现这种单参数的构造函数,C++会默认将参数对应的类型转换为该类类型,有时候这种隐私的转换是我们所不想要的,所以需要使⽤explicit来限制这种转换。
c++拷贝构造函数和赋值构造函数在C++中,对象的拷贝操作是很常见的。
对象的拷贝操作包括两种情况:一是对象的初始化,如“类名对象(obj1)=类名对象(obj2)”;二是对象的赋值,如“obj1=obj2”。
为了实现对象的拷贝操作,C++中提供了拷贝构造函数和赋值构造函数。
本文将详细介绍C++中的拷贝构造函数和赋值构造函数。
一、C++中的拷贝构造函数C++中的拷贝构造函数是一种特殊的构造函数,它用于完成一个对象到另一个对象的复制。
拷贝构造函数的定义形式如下:类名(const 类名& obj){}其中,类名为其所在类的名称,&表示引用类型,obj为其他的同类对象。
拷贝构造函数的目的是将一个对象复制到另一个对象中,使得两个对象完全相同。
下面是一个示例:class point{private:int x;int y;public:point(int x=0,int y=0):x(x),y(y){}point(const point& p):x(p.x),y(p.y){}//拷贝构造函数};在上面的代码中,point类中有一个拷贝构造函数,用于将对象p复制到当前对象中。
拷贝构造函数和普通构造函数在调用时是有区别的,普通构造函数传递的参数是要初始化的数据,而拷贝构造函数传递的参数是要复制的对象。
拷贝构造函数的使用场景有以下几种情况:1、类参数传递在函数参数中,可以通过拷贝构造函数将一个类对象传递到函数中。
如:void func(point p){cout<<p.get_x()<<","<<p.get_y()<<endl;}在上面的代码中,point类对象p被作为参数传递到func()函数中。
这里的拷贝构造函数用来完成将一个point对象(p)复制到另一个point对象中。
2、类返回值point func(){point p(1,2);return p;//将point对象p返回到主调函数中}在这里,point类的实例对象返回到主调函数中。
实验五【实验内容】构造函数和析构函数和复制构造函数构造函数1. 构造函数是类的一个特殊成员函数,它的函数名与类名相同。
2. 构造函数定义了对象数据成员的初始化方法,它只在创建对象时被系统自动调用,并且只在创建对象时调用一次,是为创建的对象分配内存空间和对数据成员进行初始化。
3. 构造函数无函数类型,没有返回值,一般都声明为公有函数。
4.C++规定,每个类必须有构造函数,没有构造函数就不能创建对象。
5.如果程序中未声明构造函数,则系统自动产生出一个默认形式的构造函数,如果提供了一个构造函数,系统就不能自动提供一个默认的构造函数。
6.构造函数可以重载,即可以定义多个参数及参数类型不同的构造函数。
复制构造函数又称拷贝构造函数,是一种特殊的构造函数,其形参为本类的对象引用。
功能是把初始值对象的每个数据成员的值都复制到新建立的对象。
如果程序员没有为类声明拷贝初始化构造函数,则编译器自己生成一个拷贝构造函数。
1. 当用类的一个对象去初始化该类的另一个对象时系统自动调用它实现拷贝赋值。
2. 若函数的形参为类对象,调用函数时,实参赋值给形参,系统自动调用拷贝构造函数。
3. 当函数的返回值是类对象时,系统自动调用拷贝构造函数。
析构函数析构函数也是特殊的类成员函数,它没有返回类型,没有参数,不能随意调用,也没有重载,只有在类的生命周期结束的时候,由系统自动调用。
析构函数和构造函数的最主要的区别:调用期不同、构造函数可以有参数可以重载。
实验1设计一个学生类stu,其中含有数据成员name、english和math,分别表示学生的姓名、英语成绩与数学成绩,使用类的成员函数output 和total输出学生的基本信息和总成绩,并完成在main函数中的相应调用。
#include <iostream>using namespace std;class stu{public:stu(char n[]="",double e=0.0,double m=0.0);~stu();void input();void output();void total();private:char name[8];double english,math;};stu::stu(char n[],double e,double m){strcpy(name,n);english=e;math=m;}stu::~stu(){}void stu::input(){cout<<"请输入学生的姓名、英语成绩与数学成绩:"<<endl;cin>>name>>english>>math;}void stu::output (){cout<<"学生的姓名、英语成绩与数学成绩:"<<name<<","<<english<<","<<math<<endl;}void stu::total (){cout<<"学生的总成绩是:"<<english+math<<endl;}void main(){stu s1("张思宁",95,80),s2;s2.input ();s1.output ();s1.total ();s2.output() ;s2.total ();}实验2练习书上112页例4-2,熟悉复制构造函数被调用的3种情况。