拷贝构造函数

拷贝构造函数是一种特殊的构造函数,它在创建对象时,使用的是同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:

l  通过使用另一个同类型的对象来初始化新创建的对象;

l  复制对象把它作为参数传递给函数;

l  复制对象,并从函数返回这个对象。

 

如果类中没有定义拷贝构造函数,编译器会自行定义一个。如果类中带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。拷贝构造函数最常见的形式如下:

classname(const classname &obj)
{//构造函数主体
}

在这里,obj是一个对象的引用,该对象是用于初始化另一个对象的。

/***
copy_constructor.cpp
***/
#include<iostream>
using namespace std;class Line
{public:Line(int len);Line(const Line & obj);~Line();    int getLength(void);private:int *ptr;
};Line::Line(int len)
{cout << "call construct func" << endl;//allocate memory for pointer    ptr = new int;*ptr = len;
}Line::Line(const Line &obj)
{cout << "call copy constructor func and allocate memory for point" << endl;ptr = new int;*ptr = *obj.ptr;
}Line::~Line(void)
{cout << "free memory" << endl;delete ptr;
}int Line::getLength(void)
{return *ptr;
}void display(Line obj)
{cout << "the size of line : " << obj.getLength() << endl;
}int main()
{Line line(10);display(line);return 0;
}

运行结果:

exbot@ubuntu:~/wangqinghe/C++/20190806$ ./copy

call construct func

call copy constructor func and allocate memory for point

the size of line : 10

free memory

free memory

 

void display(Line obj) //通过gdb调试,该程序在 Line obj处进入拷贝函数构造。

 

如果使用以下的main

int main()
{Line line1(10);Line line2 = line1;display(line1);display(line2);return 0;
}

运行结果:

exbot@ubuntu:~/wangqinghe/C++/20190806$ ./copy

call construct func

call copy constructor func and allocate memory for point

call copy constructor func and allocate memory for point

the size of line : 10

free memory

call copy constructor func and allocate memory for point

the size of line : 10

free memory

free memory

free memory

 

在C++中,对象以值传递的方式传入函数参数:

/***
value_transf.cpp
***/
#include<iostream>
using namespace std;class CExample
{public:CExample(int b){a = b;cout << "create: " << a << endl;}//copy constructorCExample(const CExample& C){a = C.a;cout << "copy constructor" << endl;}//destructor~CExample(){cout << "delete: " << a << endl;}void show(){cout << a << endl;}private:int a;
};void g_Fun(CExample C)
{cout << "test" << endl;
}int main()
{CExample test(1);g_Fun(test);return 0;
}

运行结果:

exbot@ubuntu:~/wangqinghe/C++/20190806$ g++ value_transf.cpp -o value_transf -g

exbot@ubuntu:~/wangqinghe/C++/20190806$ ./value_transf

create: 1

copy constructor

test

delete: 1

delete: 1

调用g_Fun()时,会产生以下几个重要的步骤:

1) test对象传入形参时,会先产生一个临时变量,暂且称呼C

2) 然后调用拷贝构造函数把test值给C。这两个步骤很像:CExample C

3) 等g_Fun()执行完后,析构掉C对象。

 

拷贝构造函数是一种特殊的构造函数,具有单个形参,该形参(常用const修饰)是对该类类型的引用。当定义一个新对象并用一个同类型的对象把它进行初始化时,将显示使用拷贝构造函数或从函数返回该类型的对象时,将隐式调用拷贝构造函数。

 

C++支持两种初始化形式:

拷贝初始化:int a = 5;和直接初始化 int a(5);

对于其他类型没有什么区别,对于类类型直接初始化直接调用实参匹配的构造函数,拷贝构造初始化总是调用拷贝构造函数,也就是说

A x(2);  //直接初始化,调用构造函数

A y = x; //拷贝初始化,调用拷贝构造函数。

必须定义拷贝构造函数的情况:

只包含类类型成员或内置类型(但不是指针类型)成员的类,无须显示地定义拷贝构造函数也可以拷贝;有的类有一个数据成员是指针,或者是由成员表示在构造函数中分配的其他资源,这两种情况下都必须定义拷贝构造函数。

 

以下情况使用拷贝构造函数:

类的对象需要拷贝时,拷贝构造函数将会调用。以下情况都会调用拷贝构造函数:

l  一个对象以值传递的方式进入函数体

l  一个对象以值传递的方式从函数返回

l  一个对象需要通过另外一个对象进行初始化

 

转载于:https://www.cnblogs.com/wanghao-boke/p/11310843.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384901.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux进程通信之管道

进程间完成数据传递需要借助操作系统提供的特殊的方法&#xff0c;比如&#xff1a;文件、管道、信号、共享内存、消息队列、套接字、命名管道等。但现在常用的进程间通信方式有&#xff1a; 管道 – 使用最简单 pipe 管道一般读写行为 FIFO&#xff08;有名管道&#xff09;&a…

Linux进程通信之文件

父子进程共享打开的文件描述符------使用文件完成进程间通信. /*** fork_share_fd.c***/ #include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/wait.h>int main(void) {in…

dup2函数

将当前系统中的进程信息打印到文件中 命令行&#xff1a;ps aux > out 将ps得到的信息重定向到out文件中 使用dup2文件在程序中完成。 int dup2(int oldfd,int newfd); /*** dup2.c ***/ #include<stdio.h> #include<fcntl.h> #include<unistd.h> #includ…

wait()函数

wait()函数&#xff1a;回收僵尸进程 父进程调用wait函数可以回收子进程终止信息。该函数有三个功能&#xff1a; 1&#xff09; 阻塞等待子进程退出 2&#xff09; 回收子进程残留资源 3&#xff09; 获取子进程结束状态&#xff08;退出原因&#xff09; /*** zoom_test.c **…

waitpid()函数

waitpid函数 作用同于wait&#xff0c;但可指定pid进程清理&#xff0c;可以不阻塞。 pid_t waitpid(pid_t pid,int *status,int options);成功&#xff1a;返回清理掉的子进程ID&#xff1b;失败&#xff1a;-1&#xff08;无子进程&#xff09; 特殊参数和返回情况&#xff1…

孤儿进程、僵尸进程

孤儿进程&#xff1a;父进程先于子进程结束&#xff0c;则子进程成为孤儿进程&#xff0c;子进程的父进程成为init进程&#xff0c;称为init进程领养孤儿进程。 /*** orphan.c ***/ #include <stdio.h> #include <unistd.h> #include <sys/wait.h>int main(v…

友元函数

类的友元函数是定义在类外部&#xff0c;但有权访问类的所有私有成员和保护成员。尽管友元函数的原型有在类的定义中出现过&#xff0c;但友元函数并不是成员函数。 友元可以是一个函数&#xff0c;该函数被称为友元函数&#xff1b;友元也可以是一个类&#xff0c;该类被称为友…

this指针

在C中&#xff0c;每一个对象都能够通过this指针来访问自己的地址。this指针是所有成员函数的隐含参数。因此&#xff0c;在成员函数内部&#xff0c;它可以用来指向调用对象。 友元函数是没有this指针的&#xff0c;因为友元不是类的成员&#xff0c;只有成员函数才有this指针…

静态成员

我们可以使用static关键字把类成员定义为静态的。当我们声明类的成员为静态时&#xff0c;这意味着无论创建多少个类的对象&#xff0c;静态成员都只有一个副本。 静态成员在类的所有对象都是贡献的。如果不存在其他的初始化语句&#xff0c;在创建第一个对象时&#xff0c;所有…

Linux进程通信之mmap

mmap()函数&#xff1a; void *mmap(void* addr,size_t length,int port,int flags,int fd,off_t offset); 返回&#xff1a;成功&#xff1a;返回创建的映射区首地址&#xff1b;失败&#xff1a;MAP_FAILED 宏 参数&#xff1a; addr: 建立映射区的首地址&#xff0c;由…

Linux之文件通信

/** 后执行,尝试读取另外一个进程写入文件的内容*/ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <string.h>int main(void) {char buf[1024];char *str "----------test2 write secesuss---…

重载函数和重载运算符

C允许在同一个作用域中的某个函数和运算符指定多个定义&#xff0c;分别称为函数重载和运算符重载。 重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明&#xff0c;但他们的参数列表和定义&#xff08;实现&#xff09;不相同。 当调用一个重载函数…

二元运算符重载

以非成员函数方式重载运算符 /*** overtwo.cpp ***/ #include<iostream> using namespace std;class Box {public:Box(double l 2.0,double b 2.0,double h 2.0){length l;breadth b;height h;}double getVolume(){return length*breadth*height;}private:double l…

一元运算符重载

一元运算符只对一个操作数进行操作&#xff0c;下面是一元运算符实例&#xff1a; 递增运算符&#xff08;&#xff09; 和递减运算符&#xff08;--&#xff09;一元减运算符&#xff0c;即符号&#xff08;-&#xff09;逻辑非运算符&#xff08;!&#xff09;/*** overone.c…

关系运算符重载

C语言支持各种关系运算符重载(<,>,>,<,)&#xff0c;他们可用于比较C内置的数据类型。 支持重载任意一个关系运算符&#xff0c;重载后的关系运算符可以用于比较类的对象。 /*** overrealate.cpp ***/ #include<iostream> using namespace std;class Distanc…

kill函数

kill函数/命令产生信号 kill命令产生信号&#xff1a;kill -SIGKILL pid kill函数&#xff1a;给指定进程发送指定信号(不一定杀死) int kill(pid_t pid, int sig); 成功&#xff1a;0&#xff1b;失败&#xff1a;-1 (ID非法&#xff0c;信号非法&#xff0c;普通用户杀i…

下标运算符重载

重载该运算符用于增强操作C数组的功能。 /*** subscript.cpp ***/ #include<iostream> using namespace std; const int SIZE 10;class safearay {private:int arr[SIZE];public:safearay(){register int i;for(i 0; i < SIZE ;i){arr[i] i;} }int& operator…

赋值运算符重载

重载赋值运算符&#xff08;&#xff09;&#xff0c;用于创建一个对象&#xff0c;比如拷贝构造函数。 /*** evaluate.cpp ***/ #include<iostream> using namespace std;class Distance {private:int feet;int inches;public:Distance(){feet 0;inches 0;}Distance(i…

运算符小括号重载

函数调用运算符()可以被重用于类的对象。当重载()时&#xff0c;没有创造一个新的调用函数的方式&#xff0c;相反地&#xff0c;这是创建一个可以传递任意数目参数的运算符函数。 /*** bracke.cpp ***/ #include<iostream> using namespace std;class Distance {private…

自增自减运算符重载

递增运算符&#xff08;&#xff09;和递减运算符&#xff08;--&#xff09;是C语言中两个重要的一元运算符。 /*** addMyself.cpp ***/ #include<iostream> using namespace std;class Time {private:int hours;int minutes;public:Time(){hours 0;minutes 0;}Time(i…