拷贝构造函数何时会被调用?

1. 对象以值传递的方式传入函数参数

2.对象以值传递的方式从函数返回

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

下面我们来看代码:

  1. //#include <iostream>
  2. //using namespace std;
  3.  
  4. //template <typename T, int MAX> //T:队列的类型,char,int,double,包括自己的struct 。MAX:循环队列的最大长度
  5. //class Queue
  6. //{
  7. //private:
  8. // T p[MAX];//队列用的数组
  9. // int head, tail;//头尾下标
  10. //public:
  11. // //在定义时预处理
  12. // inline Queue() { clear(); }
  13. // //预处理过程,使头尾下标都是0
  14. // inline void clear() { head = tail = 0; }
  15. // //循环队列压入:把元素压入队列,如果队尾超出了循环队列的最大长度,把队尾下标变成0
  16. // inline void push(const T& n) { p[tail++] = n; if (tail == MAX) tail = 0; }
  17. // //循环队列弹出:弹出队头元素,即在现有队列中最先加入的元素。同样使用了循环优化.
  18. // inline void pop() { if (++head == MAX) head = 0; }
  19. // //函数返回循环队列中的队头元素
  20. // inline T& top() { return p[head]; }
  21. // //判断队列是否为空
  22. // inline bool empty() {return head == tail;}
  23. //};
  24. //
  25. ////定义队列:
  26. //Queue <int/* 或者char之类的 */, 11111111/*循环队列的最大长度*/> q;
  27. ////在使用时可以直接用q.clear() 清空,q.push(x)压入要加入的元素,x = q.top() 找到队头元素, q.pop()弹出队头元素,q.empty()判队列是否为空
  28. //Queue<char,20> cq;
  29. //int main()
  30. //{
  31. // int i,n=10;
  32. // int x;
  33. // int array[10]={0,1,2,3,4,5,6,7,8,9};
  34. // char array_[10]={'a','b','c','d','e','f','g','h','i','j'};
  35. // for(i=0;i<n;i++)
  36. // {
  37. // cq.push(array_[i]);
  38. // }
  39. // for(i=0;i<n;i++)
  40. // {
  41. // cout <<cq.top()<<endl;
  42. // cq.pop();
  43. // }
  44. //
  45. // return 0;
  46. //}
  47.  
  48. //函数模板
  49. //template<typename T>
  50.  
  51. #include <stdio.h>
  52. #include <math.h>
  53. //反正切,知道两对边,求弧度(要自己转化成角度)
  54. /*int main(void)
  55. {
  56. double result;
  57. double x = 10.0, y = 10.0;
  58.  
  59. result = atan2(y, x);
  60. printf("The arc tangent ratio of %lf is %.1lf\n", (y / x), result*180/3.1415926);
  61.  
  62. return 0;
  63. }*/
  64.  
  65. //#include <stdio.h>
  66. //#include <math.h>
  67. ////传入的参数为弧度
  68. //int main(void)
  69. //{
  70. // double result, x = 0.5;
  71. //
  72. // result = sin(x);
  73. // printf("The sin() of %lf is %lf\n", x, result);
  74. // return 0;
  75. //}
  76.  
  77. //弧度转化角度:弧度*180/PI
  78. //角度转化弧度:角度*PI/180
  79.  
  80. //#include <math.h>
  81. //#include <stdio.h>
  82. //const double PI=acos(-1.0);
  83. ////sin传入的参数的是弧度
  84. //void main()
  85. //{
  86. // int z=30;
  87. // double x = 10.0, y = 10.0;
  88. // double result;
  89. // //sin30结果
  90. // printf("sin(%d)=%.2lf\n",z,sin(2*PI*z/360.0));
  91. // result=atan2(y, x); //结果返回是弧度
  92. // printf("The arc tangent ratio of %lf is %.1lf\n", (y / x), result*180/PI);
  93. // //sin45的结果
  94. // printf("sin(%.0f)=%.2lf\n",result*180/PI,sin(result)); //注意不要用%d
  95. //}
  96.  
  97. //桶排序思想
  98. //假如要排序的是数字是 2 4 5 5 5 8 8 9 1 1
  99. //#include<stdio.h>
  100. //#define length 10
  101. //int main()
  102. //{
  103. // //数组元素值全部初始化为0
  104. // int array[length]={0};
  105. // int i,j;
  106. // int n;
  107. // for(i=0;i<length;i++)
  108. // {
  109. // scanf("%d",&n);
  110. // array[n]++;
  111. // }
  112. // for (i = 0; i < length; i++)
  113. // {
  114. // for(j=0;j<array[i];j++)
  115. // printf("%d ",i);
  116. // }
  117. //
  118. // return 0;
  119. //}
  120. // Ba 2 Da 4 Ea 5 Eb 5 Ec 5 Ha 8 Hb 8 Ia 9 Aa 1 Ab 1
  121. //#include<stdio.h>
  122. //#define length 10
  123. //
  124. //struct node
  125. //{
  126. // char country[6]; //国家
  127. // int count; //金牌数
  128. //};
  129. //int main()
  130. //{
  131. // int i,j,n;
  132. // int array[10][10]={0}; //数组内的元素是结构体索引
  133. // int index[10]={0}; //存储每行队列(数组)内元素个数
  134. // struct node ary[length]={
  135. // {"Ba",2},{"Da",4},{"Ea",5},{"Eb",5},
  136. // {"Ec",5},{"Ha",8},{"Hb",8},{"Ia",9},
  137. // {"Aa",1},{"Ab",1}};
  138. // for(i=0;i<length;i++)
  139. // {
  140. // n=ary[i].count; //桶子编号
  141. // array[n][index[n]]=i; //存储结构体数组索引
  142. // index[n]++;
  143. // }
  144. // for(i=0;i<length;i++)
  145. // {
  146. // for(j=0;j<index[i];j++)
  147. // {
  148. // printf("%s %d\n",ary[array[i][j]].country,ary[array[i][j]].count);
  149. // }
  150. // }
  151. //}
  152.  
  153. //#include<stdio.h>
  154. //
  155. //int main()
  156. // {
  157. // int nVar = 0x12345678;
  158. // int *pnVar = &nVar;
  159. // char *pcVar = (char*)&nVar;
  160. // short *psnVar = (short*)&nVar;
  161. // printf("%08x \r\n", *pnVar);
  162. // printf("%08x \r\n", *pcVar);
  163. // printf("%08x \r\n", *psnVar);
  164. // return 0;
  165. // }
  166.  
  167. //拷贝构造函数
  168. // 04.cpp : Defines the entry point for the console application.
  169. //
  170.  
  171. //#include "stdafx.h"
  172. #include "iostream"
  173. using namespace std;
  174. class CDog
  175. {
  176. public:
  177. unsigned int m_Weight;
  178. unsigned int m_Age;
  179.  
  180. CDog(int weight,int age);
  181. CDog(int weight = );
  182.  
  183. CDog(const CDog & theDog);
  184.  
  185. void SetAge(unsigned int age);
  186. int GetAge ();
  187. ~CDog();
  188. };
  189.  
  190. CDog::CDog(int weight,int age)
  191. {
  192. m_Weight = weight;
  193. m_Age = age;
  194. }
  195.  
  196. CDog::CDog(int weight)
  197. {
  198. m_Weight = weight;
  199. }
  200.  
  201. CDog::CDog(const CDog & theDog)
  202. {
  203. m_Weight = theDog.m_Weight;
  204. m_Age = theDog.m_Age;
  205. printf("Copy constructor is called.\n");
  206. }
  207.  
  208. void CDog::SetAge(unsigned int age)
  209. {
  210. m_Age = age;
  211. }
  212.  
  213. int CDog::GetAge ()
  214. {
  215. return m_Age;
  216.  
  217. }
  218.  
  219. CDog::~CDog()
  220. {
  221. }
  222.  
  223. CDog CopyData(CDog m_dog)
  224. {
  225. return m_dog;
  226. }
  227.  
  228. void test(CDog tmp)
  229. {
  230.  
  231. }
  232. CDog test2()
  233. {
  234. CDog temp;
  235. cout<<"对象以值传递的方式从函数返回"<<endl;
  236. return temp;
  237. }
  238. int main(int argc, char* argv[])
  239. {
  240.  
  241. CDog Example;
  242. cout<<"对象以值传递的方式传入函数参数"<<endl;
  243. test(Example);
  244. test2();
  245. //对象需要通过另外一个对象进行初始化
  246. //这里调用的是拷贝构造函数。而不是我们看到的赋值
  247. CDog test3 = Example;
  248.  
  249. return ;
  250. }

浅拷贝与深拷贝

1.浅拷贝指的是只对对象中的数据成员进行简单的赋值。

2.默认拷贝构造函数执行的就是浅拷贝。

3.默认拷贝构造函数不会处理静态数据成员。

4.浅拷贝无法处理对象内的动态成员。

原因:浅拷贝仅仅是赋值,所以拷贝的对象的动态成员与原对象动态成员指向同一块内存,但是析构函数却会调用二次,

释放两次同一块内存,自然会出错。

5.深拷贝会在拷贝函数中为动态成员分配内存。

  1. //代码来自:
  2. //http://blog.csdn.net/lwbeyond/article/details/6202256 作者:lwbeyond
  3. #include "iostream"
  4. using namespace std;
  5. class Rect
  6. {
  7. public:
  8. Rect() // 构造函数,p指向堆中分配的一空间
  9. {
  10. p = new int();
  11. }
  12. ~Rect() // 析构函数,释放动态分配的空间
  13. {
  14. if(p != NULL)
  15. {
  16. delete p;
  17. }
  18. }
  19. private:
  20. int width;
  21. int height;
  22. int *p; // 一指针成员
  23. };
  24.  
  25. int main()
  26. {
  27. Rect rect1;
  28. Rect rect2(rect1); // 复制对象
  29. return ;
  30. }

如果运行此程序,会出错。原因上面已经阐述。

修改成深拷贝:

  1. //代码来自:
  2. //http://blog.csdn.net/lwbeyond/article/details/6202256 作者:lwbeyond
  3. #include "iostream"
  4. using namespace std;
  5. class Rect
  6. {
  7. public:
  8. Rect() // 构造函数,p指向堆中分配的一空间
  9. {
  10. p = new int();
  11. }
  12. Rect(const Rect& r)
  13. {
  14. width = r.width;
  15. height = r.height;
  16. //p = new int(100); // 为新对象重新动态分配空间
  17. p = new int; // 为新对象重新动态分配空间
  18. *p = *(r.p);
  19. }
  20. ~Rect() // 析构函数,释放动态分配的空间
  21. {
  22. if(p != NULL)
  23. {
  24. delete p;
  25. }
  26. }
  27. private:
  28. int width;
  29. int height;
  30. int *p; // 一指针成员
  31. };
  32. int main()
  33. {
  34. Rect rect1;
  35. Rect rect2(rect1); // 复制对象
  36. return ;
  37. }

成功运行。

避免调用默认拷贝构造函数的方法:

声明一个私有拷贝构造函数。

拷贝构造函数可有一个或者多个。

下面来自博客:http://blog.csdn.net/lwbeyond/article/details/6202256

对于一个类X, 如果一个构造函数的第一个参数是下列之一:
a) X&
b) const X&
c) volatile X&
d) const volatile X&
且没有其他参数或其他参数都有默认值,那么这个函数是拷贝构造函数.

http://blog.csdn.net/lwbeyond/article/details/6202256 对于拷贝构造函数解释的很详细。

拷贝构造函数[c++]的更多相关文章

  1. C++ 拷贝构造函数和赋值运算符

    本文主要介绍了拷贝构造函数和赋值运算符的区别,以及在什么时候调用拷贝构造函数.什么情况下调用赋值运算符.最后,简单的分析了下深拷贝和浅拷贝的问题. 拷贝构造函数和赋值运算符 在默认情况下(用户没有定义 ...

  2. C++ 一个例子彻底搞清楚拷贝构造函数和赋值运算符重载的区别

    class TestChild { public: TestChild() { x=; y=; printf("TestChild: Constructor be called!\n&quo ...

  3. C++ 为什么拷贝构造函数参数必须为引用?赋值构造函数参数也必须为引用吗?

    之前写拷贝构造函数的时候,以为参数为引用,不为值传递,仅仅是为了减少一次内存拷贝.然而今天看到一篇文章发现自己对拷贝构造的参数理解有误. 参数为引用,不为值传递是为了防止拷贝构造函数的无限递归,最终导 ...

  4. C++拷贝构造函数

    拷贝构造函数是一种特殊的构造函数,其定义为第一个参数为为本类型的一个引用或者是常引用,且无其它参数或者其它参数为默认值,例如下面的函数: X::X(const X&); X::X(X& ...

  5. PoEdu - C++阶段班【Po学校】- Lesson03-4_构造函数&赋值函数&拷贝构造函数&学习方式 - 第6天

    PoEdu - C++阶段班[Po学校]- 第6天 课堂选择题目: 1  关于转换构造函数  ClassDemo demo = 1;  调用转换构造函数 2  关于拷贝赋值函数  demo =2; 首 ...

  6. C++拷贝构造函数(深拷贝,浅拷贝)

    对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. #i ...

  7. C++ 拷贝构造函数 和 六大函数

    1.  C++什么时候会调用 拷贝构造函数? a.一个对象作为函数参数,以值传递的方式传入函数体: b.一个对象作为函数返回值,以值传递的方式从函数返回:(实际使用时,会被编译器优化掉) c.一个对象 ...

  8. 一个CString的实现 拷贝构造函数的应用

    class CString { public: CString (char* s); CString(); ~CString(); private: char *str; int len; stati ...

  9. 【转】C++的拷贝构造函数深度解读,值得一看

    建议看原帖  地址:http://blog.csdn.net/lwbeyond/article/details/6202256 一. 什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很 ...

  10. C++拷贝构造函数(深拷贝,浅拷贝)

    http://www.cnblogs.com/BlueTzar/articles/1223313.html 对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a;  ...

随机推荐

  1. Linux学习《第四章shell脚本练习一》随堂练习(重要)

  2. Spring容器的创建原理

    1.new ioc容器(AnnotationConfigApplicationContext 注解ioc) 2.refresh()方法调用 2.1 prepareRefresh()刷新前的预处理 a: ...

  3. 【ABP】从零开始学习ABP_入门介绍

    本文介绍自己入坑ABP的过程,一些ABP的相关文章.QQ群,以及ABP Zero示例项目的运行. 背景 作为一个半路出家学习编程的新人,之前工作中也断断续续写过一些代码,但底层核心一直没机会学习,所以 ...

  4. Python基础笔记:list和tuple

    list 与 tuple 就类似于C语言中的数组,list 与 tuple 的区别就是list 可修改,而tuple不可修改: list用法示例: >>> s=[] >> ...

  5. 使用docker快速体验kali linux

    环境 运行在 64位 机器 企业版的 win10 系统 下载镜像 首先搜索docker download 去官网下载docker:https://www.docker.com/products/doc ...

  6. ng : File C:\Users\baron\AppData\Roaming\npm\ng.ps1 cannot be loaded because running

    一. Windos PowerShell 选择 管理员身份运行二.set-ExecutionPolicy RemoteSigned 然后更改权限为A 三.get-ExecutionPolicy 查看当 ...

  7. JDK1.8 HashMap学习

    1:源码分析 1.1:构造方法 public HashMap(int initialCapacity, float loadFactor) { ) throw new IllegalArgumentE ...

  8. Unity3d中渲染到RenderTexture的原理,几种方式以及一些问题

    超级搬运工 http://blog.csdn.net/leonwei/article/details/54972653 ---------------------------------------- ...

  9. GWCTF 2019]我有一个数据库

    0x00 知识点 phpMyadmin(CVE-2018-12613)后台任意文件包含漏洞 影响版本:4.8.0--4.8.1 payload:/phpmyadmin/?target=db_datad ...

  10. 2020/2/3 PHP代码审计之PHP伪协议

    0x00 简介 开局一张图233 0x01 file://协议 说明: file:// 文件系统是 PHP 使用的默认封装协议,展现了本地文件系统.当指定了一个相对路径(不以/..\或 Windows ...