拷贝构造函数

合集下载

拷贝构造函数

拷贝构造函数

拷贝构造函数
拷贝构造函数的参数⼀定要是本类对象的引⽤,为什么?原因在待会说
拷贝构造函数的调⽤时机:
1)在定义对象时⽤本类对象初始化新定义的对象
2)本类对象作为函数参数时,调⽤函数时,实参对象会对形参进⾏初始化,那么就需要调⽤拷贝构造函数。

(这也是为什么拷贝构造函数参数必须是本类对象的引⽤,因为如果形参时本类对象,那么在调⽤拷贝构造函数时,实参对形参赋值时⼜会调⽤拷贝构造函数,出现递归调⽤拷贝构造函数,并且⼀直递归下去)
3)本类对象作为函数返回值,返回时创建⼀个临时对象,⽤返回的对象初始化临时对象,会调⽤拷贝构造函数。

然后临时对象赋值给主函数中的对象,接着会析构临时对象(调⽤析构函数)。

拷贝构造函数显式定义时机:
当类的构造函数中有动态申请的空间时,需要显式定义⼀个拷贝构造函数,实现“深拷贝”,即对新对象重新申请同样⼤⼩的动态存储空间,并把已知对象的动态存储空间的内容复制到新对象的动态存储空间。

因为当类的数据成员中有动态申请的数据空间,如果不定义拷贝构造函数,⽽使⽤类中默认的拷贝构造函数,对象会进⾏“浅拷贝”,拷贝后,即两个对象的指针会指向同⼀个内存空间,最后在析构对象时,会对同⼀个内存空间析构两次,出现运⾏错误。

shared_ptr 拷贝构造

shared_ptr 拷贝构造

shared_ptr 拷贝构造shared_ptr 拷贝构造函数会创建一个新的 shared_ptr 对象,其中包含原始 shared_ptr 对象指向的资源的副本。

拷贝构造函数的形式如下:```shared_ptr(const shared_ptr<T>& other);```其中,other 是另一个 shared_ptr 对象。

拷贝构造函数会递增资源的引用计数,以表示新的 shared_ptr对象也指向同一资源。

这样一来,原始 shared_ptr 对象和新的shared_ptr 对象就可以同时拥有资源,并在不同的作用域中管理和访问它。

需要注意的是,拷贝构造函数只会递增引用计数,不会创建资源的副本,因此原始 shared_ptr 对象和新的 shared_ptr 对象会共享同一个资源。

只有当引用计数降为零时,资源才会被销毁。

以下是一个示例:```cpp#include <iostream>#include <memory>int main() {std::shared_ptr<int> ptr1(new int(10));std::cout << "ptr1: " << *ptr1 << std::endl; // 输出: 10std::shared_ptr<int> ptr2(ptr1); // 使用拷贝构造函数创建新的shared_ptr 对象std::cout << "ptr1: " << *ptr1 << std::endl; // 输出: 10std::cout << "ptr2: " << *ptr2 << std::endl; // 输出: 10return 0;}```在上述示例中,ptr1 是一个指向整数的 shared_ptr 对象。

简述构造函数、析构函数和拷贝构造函数的特点和用途

简述构造函数、析构函数和拷贝构造函数的特点和用途

简述构造函数、析构函数和拷贝构造函数的特点和用途构造函数、析构函数和拷贝构造函数是C++中用于对象创建、销毁和复制的重要概念。

以下是它们的主要特点和用途:1. 构造函数构造函数用于创建对象实例。

它是一个函数指针,指向一个函数,该函数接受一个对象变量作为参数,并返回一个新的对象。

构造函数的特点是在于它的参数是一个对象变量,而不是一个对象。

这使得构造函数可以用于创建对象的临时副本。

构造函数通常被标记为成员函数,并且需要使用关键字static 修饰。

在类中,构造函数称为构造函数,它的实现是对象的初始化。

如果构造函数没有返回值,则默认情况下它会抛异常。

2. 析构函数析构函数用于销毁对象实例。

它是一个函数指针,指向一个函数,该函数接受一个对象变量作为参数,并返回一个未使用的变量。

在对象销毁之前,析构函数会执行对象变量的销毁操作。

析构函数通常被标记为成员函数,并且需要使用关键字static 修饰。

在类中,析构函数称为析构函数,它的实现是对象的销毁。

如果对象中包含共享资源(例如内存对象或文件句柄),那么在对象销毁之前,必须确保这些资源也被销毁。

3. 拷贝构造函数拷贝构造函数用于复制对象。

它是一个函数指针,指向一个函数,该函数接受一个对象变量作为参数,并返回一个新的对象。

拷贝构造函数的特点是在于它复制的是对象的实际值,而不是对象的对象。

拷贝构造函数通常被标记为成员函数,并且需要使用关键字public修饰。

在类中,拷贝构造函数用于复制对象。

如果类中包含共享资源,那么在复制对象之前,必须确保这些资源也被复制。

构造函数、析构函数和拷贝构造函数是C++中用于对象创建、销毁和复制的重要概念。

它们使得对象的创建和销毁更加简单、安全和高效。

拷贝构造函数被调用的三种情况

拷贝构造函数被调用的三种情况

拷贝构造函数被调用的三种情况一、引言拷贝构造函数是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++拷贝(复制)构造函数详解⼀. 什么是拷贝构造函数⾸先对于普通类型的对象来说,它们之间的复制是很简单的,例如:[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) 就是我们⾃定义的拷贝构造函数。

默认拷贝构造函数

默认拷贝构造函数

默认拷贝构造函数
1 拷贝构造函数
拷贝构造函数是 C ++ 中重构语言特性之一,它用来拷贝一个对
象到另一个对象,从而实现了对象的复制。

例如,一个基类可以拷贝
到子类,而不是使用的子类的构造函数,以实现”父子”的拷贝构造
函数。

在 C++ 中,拷贝构造函数是一种特殊的函数,它由编译器自动生成。

对对象及其子对象/部分进行浅拷贝,而不是全部拷贝。

默认情况下,编译器会为每个类生成一个无参的拷贝构造函数,也可以加入自
定义的拷贝构造函数,它可以完成深度拷贝。

拷贝构造函数有四种使用情况:当一个对象直接或间接初始化为
另一个对象;当对象赋值给另一个对象;当一个对象被压入一个容器;当一个对象从一个容器取出。

由于它的默认构建函数行为,可以使用
默认的拷贝构造函数和赋值运算符在不同的类之间的简单的实例赋值。

拷贝构造函数也有一些缺点。

由于它只是对对象及其子对象/部分
进行浅拷贝,它只能在表面上复制,而不能实现真正的拷贝,所以无
法处理复杂数据类型。

当类中存在指针拷贝时,拷贝构造函数也存在
一些问题,因为一个指针拷贝另一个指针,并不能实现真正的拷贝,
而只是拷贝一个指针的值。

总而言之,拷贝构造函数是 C++ 中重要的特性,它在默认模式下可以使用简单的实例赋值,但也存在其自身的一些局限性,一些复杂数据类型和指针拷贝时存在许多问题,应该避免使用。

类的四个默认成员函数-拷贝构造函数

类的四个默认成员函数-拷贝构造函数

类的四个默认成员函数-拷贝构造函数2.拷贝构造函数1.拷贝构造函数的概念 拷贝构造函数是⼀种特殊的构造函数,负责类对象之间的复制,与构造函数相同,当我们没有实现拷贝构造函数时,编译器会为我们产⽣默认拷贝构造函数,举个栗⼦: class A{public:A(int _a,int _b) : a(_a),b(_b){std::cout << "A constructors" << std::endl;}A(const A& rhs){this->a = rhs.a;this->b = rhs.b;std::cout << "A copy constructors" << std::endl;}int a;int b;};int main(){A a(13,14);std::cout << a.a << "," << a.b << std::endl;A b(a);std::cout << b.a << "," << b.b << std::endl;return0;}测试结果为:A constructors13,14A copy constructors13,14可以看到,b直接利⽤a的值为⾃⼰完成了对象的创建和赋值。

2.拷贝构造函数的调⽤时机在C++中,在三种情况下会发⽣拷贝构造的调⽤1.对象以值传递的⽅式传⼊函数参数假设存在函数fun(Class_A a){},当调⽤函数fun(A a)时,⼀个Class_A类型的对象被传⼊。

我们知道,函数形参传⼊,需要⽣成临时对象.假设传⼊⼀个Class_A的对象tset,当test传⼊时,产⽣临时对象,调⽤拷贝构造函数将test的值传给临时对象,执⾏完fun()之后,析构掉临时对象。

第三章(6)拷贝构造函数

第三章(6)拷贝构造函数

第三章(6)拷贝构造函数⼀、拷贝构造函数:对于普通类型的对象来说,他们之间的复制是很简单的,例如:int a = 10;int b =a;⾃⼰定义的类的对象同样是对象,他们之间的特性有相似之处也有不同之处,类对象内部存在成员变量,⽽普通对象是没有的,当同样的复制⽅法发⽣在不同的对象上的时候,那么系统对他们进⾏的操作也是不⼀样的,就类对象⽽⾔,相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。

当⽤⼀个已有的对象初始化另⼀个对象时编译器⾃动调⽤拷贝构造函数。

拷贝构造函数只发⽣在初始化阶段。

⼆、⽰例⽰例1:#include <iostream.h>#include <string.h>class Student{public:Student(char* pName="no name",int ssId=0);Student(Student& s); //拷贝构造函数~Student();protected:char name[40];int id;};Student::Student(char* pName, int ssId){strncpy(name,pName,40);name[39]='\0';id = ssId;cout <<"Constructing new student " <<pName <<endl;}Student::Student(Student& s) //拷贝构造函数{cout <<"Constructing copy of " << <<endl;strcpy(name,"copy of ");strcat(name,);id=s.id;}Student::~Student(){cout <<"Destructing " <<name <<endl;}void fn(Student s){cout <<"In function fn()\n";}void main(){Student randy("Randy",1234);cout <<"Calling fn()\n";fn(randy);cout <<"Returned from fn()\n";}分析:上⾯代码中的Student::Student(Student& s);就是我们⾃定义的拷贝构造函数,拷贝构造函数的名称必须与类名称⼀致,函数的形式参数是本类型的⼀个引⽤变量,且必须是引⽤。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验7拷贝构造函数
一、实验目的
(1) 掌握类的声明和对象的声明。

(2) 掌握拷贝构造函数的定义与使用
(3) 了解拷贝构造函数调用的时机
二、实验内容及步骤
1 新建c++源文件,找到week14文件夹中的copyStruDefine.cpp文件,复制到新建的源文件中运行,将运行结果记录下来,分析程序中执行哪条语句引起拷贝构造函数被调用的,将该语句的行号记录下来。

分析程序,第46 条语句Point pa(1,2) 执行时会调用构造函数,第47 条语句
Point pb=pa 执行时会调用拷贝构造函数。

2 程序中添加一个distance函数,用来计算2个点之间的距离。

代码如下:
运行程序,记录运行结果。

分析程序,第52,53 条语句Point pa(7,4); Point pb(1,2); 执行时会调用构造函数,第46,47 条语句
double dx=a1.getX()-a2.getX();double dy=a1.getY()-a2.getY(); 执行时会调用拷贝构造函数。

3 设计一个函数mirror用来返回一个点在x轴的镜像坐标,如点A坐标为(1,2),它的镜像点A’坐标为(1,-2)。

分析:函数的结构分成2部分,函数头部和函数体
(1)函数的函数头部分语法格式:返回类型函数名(参数)
可以确定的是函数名mirror;这个函数会计算出一个点的镜像并返回,点的镜像还是一个点,因此可以确定函数的返回类型是void ;这个函数会将某个点的镜像计算出来,那到底计算的是那个点的镜像呢?这是不确定的,将不确定的因素定义为函数的参数,因此函数的参数类型是Point ;现将函数的第一行补充完整。

返回类型mirror(参数)
(2)分析函数的函数体部分,即用”{ }”包围的部分。

我们通过参数传递接收到一个点的坐标,现在要计算另一个点的坐标(镜像点),因此需要在函数体内定义另外一个点类型的对象来存放镜像点的坐标。

将镜像点的x坐标赋值为参数点的x坐标值,将镜像点的y坐标赋值为参数点的y坐标值的负数值(需要注意Point类中的x和y成员都是私有的)。

将镜像点坐标赋值完成后,用return语句将镜像点返回。

(3)在主函数中测试mirror函数。

#include <iostream>
#include <math.h>
using namespace std;
/*
类的函数成员-->构造函数(创建对象并赋初值)
int a=10;
int b=a;//创建变量b并赋初值,这个初值放在a中
创建对象(新)时,构造函数的参数是对象(已存在)
--拷贝构造函数
*/
class Point{
private:
double x;
double y;
public:
//拷贝构造函数是构造函数
//参数和普通的构造函数不同
//是同类型对象的引用参数
Point (Point & q){
x= q.x;
y=q.y ;
cout<<"拷贝构造函数被调用\n";
}
Point(double a1=0,double a2=0){
x=a1;
y=a2;
cout<<"构造函数被调用\n";
}
void display(){
cout<<"("<<x<<","<<y<<")"<<endl;
}
void setPoint(double a,double b){
x=a;
y=b;
}
double getX(){
return x;
}
double getY(){
return y;
}
};
/*此处添加distance函数,计算2点之间的距离*/
class operatePoint{
public:
void distance(Point a1,Point a2){
double len;
double dx=a1.getX()-a2.getX();
double dy=a1.getY()-a2.getY();
len=sqrt(dx*dx+dy*dy);
cout<<"distance="<<len<<endl;
}
Point mirror(Point a1){
Point pa;
pa.setPoint(a1.getX(),-a1.getY());
return pa;
}
};
void main(){
Point pa(7,4);
Point pb(1,2);//语法,Point pb(pa);
operatePoint op;
pa.display();
pb.display();
op.distance(pa,pb);
cout<<"pa的镜像点坐标";
op.mirror(pa).display();
}。

相关文档
最新文档