zl程序教程

您现在的位置是:首页 >  后端

当前栏目

【C/C++学院】(6)构造函数/析构函数/拷贝构造函数/深copy浅copy

C++ 函数 拷贝 构造函数 copy 学院 析构
2023-09-14 08:57:16 时间
3.拷贝构造函数

拷贝构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构建及初始化。其唯一的形参必须是引用,但并不限制为const,一般普遍的会加上const限制。此函数经常用在函数调用时用户定义类型的值传递及返回。拷贝构造函数要调用基类的拷贝构造函数和成员函数。如果可以的话,它将用常量方式调用,另外,也可以用非常量方式调用。

当我们没有编写拷贝构造函数的时候,c++编译器会默认给我们提供一个拷贝构造函数,执行的是浅拷贝。

copy构造函数四种应用场景;

第一种场景:=

#include iostream 

using namespace std;

class CExample {

private:

 int a;

public:

 //构造函数

 CExample(int b)

 a = b;

 //拷贝构造函数

 CExample(const CExample C)

 a = C.a;

 //一般函数

 void Show()

 cout a endl;

int main()

 CExample A(100); 

 CExample B = A; //注意这里的对象初始化要调用拷贝构造函数,而非赋值

 // CExample B(A); 也是一样的

 B.Show();

 return 0;

} 

第二种场景:()

#include iostream 

using namespace std;

class CExample {

private:

 int a;

public:

 //构造函数

 CExample(int b)

 a = b;

 //拷贝构造函数

 CExample(const CExample C)

 a = C.a;

 //一般函数

 void Show()

 cout a endl;

int main()

 CExample A(100); 

 //CExample B = A; //注意这里的对象初始化要调用拷贝构造函数,而非赋值

 CExample B(A); //也是一样的

 B.Show();

 return 0;

} 

第三种场景:对象以值传递的方式传入函数参数

#include iostream 

using namespace std;

class CExample

private:

 int a;

public:

 //构造函数 

 CExample(int b)

 a = b;

 cout "creat: " a endl;

 //拷贝构造 

 CExample(const CExample C)

 a = C.a;

 cout "copy" endl;

 //析构函数 

 ~CExample()

 cout "delete: " a endl;

 void Show()

 cout a endl;

//全局函数,传入的是对象 

void g_Fun(CExample C)

 cout "test" endl;

int main()

 CExample test(1);

 //传入对象 

 g_Fun(test);

 return 0;

} 

第四种场景:对象以值传递的方式从函数返回

#include iostream 

using namespace std;

class CExample

private:

 int a;

public:

 //构造函数 

 CExample(int b=0)

 a = b;

 cout "a:" a endl;

 ~CExample()

 cout "destroy a:" a endl;

 //拷贝构造 

 CExample(const CExample C)

 a = C.a;

 cout "copy a:" a endl;

//全局函数 

CExample g_Fun()

 CExample temp(10);

 return temp;

int main()

 CExample ret;

 ret = g_Fun();

 return 0;

} 
添加断点,逐条语句运行,观察程序的执行步骤以及打印输出:


4.深copy浅copy

    在某些状况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝,也就是把对象里的值完全复制给另一个对象,如A=B。这时,如果B中有一个成员变量指针已经申请了内存,那A中的那个成员变量也指向同一块内存。这就出现了问题:当B把内存释放了(如:析构),这时A内的指针就是野指针了,出现运行错误。

深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。

#include "iostream"

using namespace std;


name obj1("name1"); //如果你不写copy构造函数,那么C++编译器会给我们提供一个默认的copy构造函数 (浅cpy) name obj2 = obj1; //如果你不写=操作,那么C++编译器会给我们提供一个=操作函数 (浅cpy) obj2 = obj1; cout obj2.getPn() endl; void main() playmain(); system("pause"); }


#define _CRT_SECURE_NO_WARNINGS

#include "iostream"

using namespace std;

class name

public:

 name(char *pn);

 name(name obj)

 cout " copy Constructing " endl;

 char *pn = obj.getPn();

 pname = (char *)malloc(strlen(pn) + 1);

 if (pname != NULL) strcpy(pname, pn);

 //pname = new char[strlen(pn)+1] ;

 //if (pname!=0) strcpy(pname,pn) ;

 size = strlen(pn);

 ~name();

protected:

 char *pname; int size;

public:

 char * getPn()

 return pname;

 void operator=(name obj1)

 cout " 执行=操作" endl;

 if (pname != NULL)//此处有一个疑问:如果不free, 直接将原来的内存进行重新赋值

 char *pn = obj1.getPn();

 strcpy(pname, pn);

 pname[0] = N;

 size = strlen(pn);

 void operator=(name obj1)

 cout " 执行=操作" endl ;

 if (pname != NULL)//此处有一个疑问:如果不free, 直接将原来的内存进行重新赋值

 free(pname);

 pname = NULL;

 size = 0;

 char *pn = obj1.getPn();

 pname = (char *)malloc(strlen(pn) +1);

 if (pname!=NULL) strcpy(pname,pn) ;

 //pname = new char[strlen(pn)+1] ;

 //if (pname!=0) strcpy(pname,pn) ;

 pname[0] = m;

 size = strlen(pn) ;

name::name(char *pn)

 cout " Constructing " pn endl;

 pname = (char *)malloc(strlen(pn) + 1);

 if (pname != 0) strcpy(pname, pn);

 //pname = new char[strlen(pn)+1] ;

 //if (pname!=0) strcpy(pname,pn) ;

 size = strlen(pn);

name :: ~name()

 cout " Destructing " pname endl;

 pname[0] = \0;

 //delete []pname ;

 free(pname);

 size = 0;

int playmain()

 name obj1("name1");

 name obj3("name3");

 //如果你不写copy构造函数,那么C++编译器会给我们提供一个默认的copy构造函数 (浅cpy)

 name obj2 = obj1;

 //做业务逻辑

 //此处省略500行

 //如果你不写=操作,那么C++编译器会给我们提供一个=操作函数 (浅cpy)

 //会调用对象2 的=号操作函数, obj3是形参, obj2干什么去了?

 obj2 = obj3;

 cout obj2.getPn() endl;

 return 0;

int main()

 playmain();

 //system("pause");

 return 0;

}

最终分析图:




高效学 C++|组合类的构造函数 设计好MyString类后,就可以像使用普通类型一样使用它了。例如,类的对象可以像普通的变量一样作为另一个类的数据成员。
【C++要笑着学】类的默认成员函数详解 | 构造函数 | 析构函数 | 构造拷贝函数(二) 朋友们好啊,今天终于更新了。我是柠檬叶子C,本章将继续讲解C++中的面向对象的知识点,本篇主要讲解默认成员函数中的构造函数、析构函数和拷贝构造函数。还是和以前一样,我们将由浅入深地去讲解,以 初学者 的角度去探索式地学习。会一步步地推进讲解,而不是直接把枯燥的知识点倒出来,应该会有不错的阅读体验。如果觉得不错,可以 一键三连 支持一下博主!你们的关注就是我更新的最大动力!Thanks ♪ (・ ・)ノ
【C++要笑着学】类的默认成员函数详解 | 构造函数 | 析构函数 | 构造拷贝函数(一) 朋友们好啊,今天终于更新了。我是柠檬叶子C,本章将继续讲解C++中的面向对象的知识点,本篇主要讲解默认成员函数中的构造函数、析构函数和拷贝构造函数。还是和以前一样,我们将由浅入深地去讲解,以 初学者 的角度去探索式地学习。会一步步地推进讲解,而不是直接把枯燥的知识点倒出来,应该会有不错的阅读体验。如果觉得不错,可以 一键三连 支持一下博主!你们的关注就是我更新的最大动力!Thanks ♪ (・ ・)ノ