C++拷贝构造函数的几个细节
详解C++中构造函数,拷贝构造函数和赋值函数的区别和实现

详解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)如果⽤户没有⾃定义拷贝构造函数,并且在代码中使⽤到了拷贝构造函数,编译器就会⽣成默认的拷贝构造函数。
拷贝构造函数的用法-电脑资料

拷贝构造函数的用法-电脑资料jiu_acm纸上得来终觉浅绝知此事要躬行拷贝构造函数的用法1.拷贝构造函数是与类名相同,其形参是本类的对象的引用,。
2.拷贝构造函数会在以下三种情况下被调用:1).当用类的一个对象去初始化该类的另一个对象时。
2).如果函数的形参是类的对象,调用该函数,将对象作为函数实参传递给函数的形参时。
3).如果函数的返回值是类的对象,函数执行完成,将返回值返回时。
3.浅拷贝的失败例子:1 #include2 #include34 using namespace std;567 class str8 {9 private:10 char *s;11 int len;12 public:13 str()14 {15 len=0;16 s=NULL;17 }18 str(const char *p)19 {20 len=strlen(p);21 s=new char[len+1];22 strcpy(s,p);23 }24 ~str()25 {26 if(s!=NULL)27 {28 delete []s;29 s=NULL;30 }31 }32 };3334 int main()35 {36 str s1("I love you!");37 str s2=s1; //这里会发生错误,电脑资料《拷贝构造函数的用法》(https://www.)。
38 return 0;39 }之所以发生错误是因为两个对象在析构时都要delete那块堆里的内存,但是程序里是浅拷贝,也就是说,s2只拷贝了s1的堆内存的地址,s2的s指针指向s1申请的堆内存,两次delete同一块内存,明显不合法。
故而需要增加自定义拷贝构造函数,即深拷贝。
见于下例:1 str(str &r)2 {3 len=r.len;4 if(len!=0)5 {6 s=new char[len+1];7 strcpy(s,r.s);8 }9 }4.注意:1).在自定义拷贝构造函数后,缺省拷贝构造函数和构造函数失效,构造函数需要自定义。
c++ 复制构造函数 拷贝构造函数

c++ 复制构造函数拷贝构造函数C++中的复制构造函数,也称为拷贝构造函数,是一种特殊的构造函数,它的作用是用一个已经存在的对象去初始化一个新的对象。
当我们没有定义复制构造函数时,C++会自动生成一个默认的复制构造函数,它的实现方法是将一个对象的每个成员变量的值都复制到新对象中。
但是,当对象中存在指针类型的成员变量时,简单的值复制可能会导致内存泄漏等问题。
因此,我们需要手动实现复制构造函数,以确保正确地复制对象。
复制构造函数的定义格式如下:ClassName(const ClassName &obj)其中,ClassName是类名,obj是待复制的对象。
在复制构造函数中,一般需要做以下几个步骤:1. 判断待复制对象和新对象是否是同一个对象,如果是,则不需要复制。
2. 分配内存空间,对新对象进行初始化。
3. 将待复制对象的成员变量值复制到新对象中。
如果存在指针类型的成员变量,则需要进行深拷贝,即重新分配内存空间并将指针指向的值复制到新内存中。
4. 返回新对象。
下面是一个示例代码:```class Person {public:Person() {name = new char[20];age = 0;}Person(const Person &obj) { if (&obj == this) {return;}name = new char[20];strcpy(name, );age = obj.age;}~Person() {delete[] name;}private:char *name;int age;};```在上面的代码中,我们定义了一个包含指针类型成员变量的类Person,并手动实现了复制构造函数。
在复制构造函数中,我们首先判断待复制对象和新对象是否是同一个对象,如果是,则不需要进行复制。
然后,我们重新分配内存空间,将待复制对象的成员变量值复制到新对象中,并对指针类型成员变量进行了深拷贝。
拷贝构造函数被调用的三种情况

拷贝构造函数被调用的三种情况一、引言拷贝构造函数是C++中的一个重要概念,它用于创建一个新对象,该对象与原始对象具有相同的值和属性。
在C++中,拷贝构造函数被广泛应用于各种编程场景中,比如对象作为函数参数传递、对象作为返回值返回等等。
本文将介绍拷贝构造函数被调用的三种情况。
二、第一种情况:使用一个对象初始化另一个对象当使用一个已经存在的对象来初始化另一个新的对象时,就会调用拷贝构造函数。
这通常发生在以下情况下:1. 对象作为函数参数传递当将一个对象作为函数参数传递时,如果该参数没有被声明为引用类型,则会调用拷贝构造函数。
例如:```void func(MyClass obj){// do something}MyClass obj1;func(obj1);```上面代码中,obj1是MyClass类的一个实例化对象,在调用func()函数时将obj1作为参数传递给了该函数。
由于obj1不是引用类型,因此会调用拷贝构造函数来创建一个新的MyClass类的实例化对象,并将其初始化为obj1。
2. 对象作为返回值返回当将一个已经存在的对象作为返回值返回时,也会调用拷贝构造函数。
例如:```MyClass func(){MyClass obj;// do somethingreturn obj;}MyClass obj1 = func();```上面代码中,func()函数返回了一个MyClass类的实例化对象obj。
由于obj是一个局部变量,当函数返回时,其内存空间将被释放。
此时,编译器会调用拷贝构造函数来创建一个新的MyClass类的实例化对象,并将其初始化为obj。
三、第二种情况:使用一个对象初始化另一个对象数组当使用一个已经存在的对象来初始化另一个对象数组时,也会调用拷贝构造函数。
例如:```MyClass obj1;MyClass arr[3] = {obj1, obj1, obj1};```上面代码中,定义了一个MyClass类的实例化对象obj1和一个包含3个元素的MyClass类的对象数组arr。
C++拷贝(复制)构造函数详解

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++编程析构函数拷贝构造函数使用示例详解

C++编程析构函数拷贝构造函数使⽤⽰例详解⽬录构造函数析构函数拷贝构造之深拷贝和浅拷贝深浅拷贝区别⾸先定义⼀个类进⾏操作。
class MM{public:protected:int year;string name;}构造函数在类中默认有⼀个⽆参的构造函数默认的构造函数为类名(){};这个构造函数如果直接写了构造函数那么这个构造函数将会没有构造函数class MM{public://MM() {};//⽆参构造函数MM(int year, string name) :year(year), name(name) {};//有参构造函数在定义对象的时候必须传参数,没参数会报错MM(int year, string name){this->name = name;this->year = year;}//这两个是⼀样的MM(int year, string name = "") :year(year) {};//因为string 是缺省的如果写没有构造默认为空就是 MM mm(15);这⾥mm对象year=15 name=“”;//缺省只能左边到右边protected:int year;string name;};析构函数MM(){};就是对构建的对象进⾏销毁析构函数的使⽤是⼀个⾃动调⽤的过程不需要⼈为进⾏,当对象的⽣命周期结束⾃动释放//析构函数需要注意的点1.当对象存在指针的时候使⽤析构函数时,析构函数⾥⾯需要释放指针的指向class MM{public:MM(const char* str){strcpy(this->str, str);}~MM() { delete[] str; };//这⾥需要释放str内存不然析构函数只会释放类不会释放strprotected:int year;string name;char* str;};int main(){MM mm("kkk");return 0;}如果类中没有指针就不⽤在析构函数中去释放指针指向拷贝构造(对对象进⾏赋值)//直接调⽤拷贝构造不调⽤构造函数MM mm(15,"kkk");//拷贝构造的⼆种⽅式对对象进⾏赋值MM mm1(mm);MM mm2 = mm;mm1.printfMM();mm2.printfMM();如果是通过匿名创建时匿名对象调⽤构造函数MM mm3 = MM(16, "jfsdl");mm3.printfMM();然后匿名对象赋值给对象调⽤的是拷贝构造函数拷贝构造之深拷贝和浅拷贝//浅拷贝默认也是浅拷贝就是赋值拷贝MM(const MM&object){this->str = object.str;}//深拷贝//深拷贝就是通过指针申请指向然后进⾏赋值MM(const MM& object){int len = strlen(object.str) + 1;this->str = new char[len];strcpy(str, object.str);}深浅拷贝区别浅拷贝就是进⾏了赋值操作深拷贝是通过申请指针后再进⾏赋值(深拷贝析构函数要释放申请的指针)谢谢⼤家的阅读,如有不⾜请及时指出,万分感激以上就是C++编程析构函数拷贝构造函数使⽤⽰例详解的详细内容,更多关于C++编程析构函数拷贝构造函数的资料请关注其它相关⽂章!。
c++拷贝构造函数(重点在内含指针的浅拷贝和深拷贝)

c++拷贝构造函数(重点在内含指针的浅拷贝和深拷贝)今天同事问了⼀个关于拷贝构造函数的问题,类中包含指针的情况,今天就来说说c++的拷贝构造函数。
c++的拷贝构造函数是构造函数的⼀种,是对类对象的初始化,拷贝构造函数只有⼀个参数就是本类的引⽤。
注意,默认构造函数(即⽆参构造函数)不⼀定存在,但是拷贝构造函数总是会存在。
下⾯是⼀个拷贝构造函数的例⼦。
1 #include<iostream>2using namespace std;3class A{4public:5int a;6 A(int value){7 a = value;8 }9void show(){10 cout<<a<<endl;11 }12 };13int main(){14 A test_a(10);15 test_a.show();1617 A test_b(test_a);18 test_b.show();1920return0;21 }输出结果为:1010如果编写了拷贝构造函数,则默认拷贝构造函数就不存在了。
下⾯是⼀个⾮默认拷贝构造函数的例⼦。
1 #include<iostream>2using namespace std;3class A{4public:5int a;6 A(int value){7 a = value;8 }9 A(A& tmp){10 a = tmp.a;11 cout<<"call copy construct"<<endl;12 }13void show(){14 cout<<a<<endl;15 }16 };17int main(){18 A test_a(10);19 test_a.show();2021 A test_b(test_a);22 test_b.show();2324return0;25 }输出结果为:10call copy construct10拷贝构造函数在以下三种情况下会被调⽤。
C++拷贝构造函数和赋值构造函数

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传给构造函数,以⽤来作复制。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
C++拷贝构造函数的几个细节
关键字: c++
拷贝构造函数是C++最基础的概念之一,大家自认为对拷贝构造函数了解么?请大家先回答一下三个问题:
1.以下函数哪个是拷贝构造函数,为什么?
1.X::X(const X&);
2.X::X(X);
3.X::X(X&, int a=1);
4.X::X(X&, int a=1, b=2);
2.一个类中可以存在多于一个的拷贝构造函数吗?
3.写出以下程序段的输出结果, 并说明为什么?如果你都能回答无误的话,那么你已经对拷贝构造函数有了相当的了解。
1.#include <iostream></iostream>
2.#include <string></string>
3.
4.struct X {
5. template<typename T>
6. X( T& ) { std::cout << "This is ctor." << std::endl; }
7.
8. template<typename T>
9. X& operator=( T& ) { std::cout << "This is ctor." << std::
endl; }
10.};
11.
12.void main() {
13. X a(5);
14. X b(10.5);
15. X c = a;
16. c = b;
17.}
解答如下:
1. 对于一个类X,如果一个构造函数的第一个参数是下列之一:
a) X&
b) const X&
c) volatile X&
d) const volatile X&
且没有其他参数或其他参数都有默认值,那么这个函数是拷贝构造函数.
1.X::X(const X&); //是拷贝构造函数
2.X::X(X&, int=1); //是拷贝构造函数
2.类中可以存在超过一个拷贝构造函数,
1.class X {
2.public:
3. X(const X&);
4. X(X&); // OK
5.};
注意,如果一个类中只存在一个参数为X&的拷贝构造函数,那么就不能使用const X或volatile X的对象实行拷贝初始化.
1.class X {
2.public:
3. X();
4. X(X&);
5.};
6.
7.const X cx;
8.X x = cx; // error
如果一个类中没有定义拷贝构造函数,那么编译器会自动产生一个默认的拷贝
构造函数.
这个默认的参数可能为X::X(const X&)或X::X(X&),由编译器根据上下文决定选择哪一个.
默认拷贝构造函数的行为如下:
默认的拷贝构造函数执行的顺序与其他用户定义的构造函数相同,执行先父类后子类的构造.
拷贝构造函数对类中每一个数据成员执行成员拷贝(memberwise Copy)的动作.
a)如果数据成员为某一个类的实例,那么调用此类的拷贝构造函数.
b)如果数据成员是一个数组,对数组的每一个执行按位拷贝.
c)如果数据成员是一个数量,如int,double,那么调用系统内建的赋值运算符
对其进行赋值.
3. 拷贝构造函数不能由成员函数模版生成.
1.struct X {
2. template<typename T>
3. X( const T& ); // NOT copy ctor, T can't be X
4.
5. template<typename T>
6. operator=( const T& ); // NOT copy ass't, T can't be X
7.};
8.
原因很简单, 成员函数模版并不改变语言的规则,而语言的规则说,如果程序需
要一个拷贝构造函数而你没有声明它,那么编译器会为你自动生成一个. 所以
成员函数模版并不会阻止编译器生成拷贝构造函数, 赋值运算符重载也遵循同样的规则.(参见Effective C++ 3edition, Item45)。