拷贝构造函数[c++]
拷贝构造函数何时会被调用?
1. 对象以值传递的方式传入函数参数
2.对象以值传递的方式从函数返回
3.对象需要通过另外一个对象进行初始化
下面我们来看代码:
- //#include <iostream>
- //using namespace std;
- //template <typename T, int MAX> //T:队列的类型,char,int,double,包括自己的struct 。MAX:循环队列的最大长度
- //class Queue
- //{
- //private:
- // T p[MAX];//队列用的数组
- // int head, tail;//头尾下标
- //public:
- // //在定义时预处理
- // inline Queue() { clear(); }
- // //预处理过程,使头尾下标都是0
- // inline void clear() { head = tail = 0; }
- // //循环队列压入:把元素压入队列,如果队尾超出了循环队列的最大长度,把队尾下标变成0
- // inline void push(const T& n) { p[tail++] = n; if (tail == MAX) tail = 0; }
- // //循环队列弹出:弹出队头元素,即在现有队列中最先加入的元素。同样使用了循环优化.
- // inline void pop() { if (++head == MAX) head = 0; }
- // //函数返回循环队列中的队头元素
- // inline T& top() { return p[head]; }
- // //判断队列是否为空
- // inline bool empty() {return head == tail;}
- //};
- //
- ////定义队列:
- //Queue <int/* 或者char之类的 */, 11111111/*循环队列的最大长度*/> q;
- ////在使用时可以直接用q.clear() 清空,q.push(x)压入要加入的元素,x = q.top() 找到队头元素, q.pop()弹出队头元素,q.empty()判队列是否为空
- //Queue<char,20> cq;
- //int main()
- //{
- // int i,n=10;
- // int x;
- // int array[10]={0,1,2,3,4,5,6,7,8,9};
- // char array_[10]={'a','b','c','d','e','f','g','h','i','j'};
- // for(i=0;i<n;i++)
- // {
- // cq.push(array_[i]);
- // }
- // for(i=0;i<n;i++)
- // {
- // cout <<cq.top()<<endl;
- // cq.pop();
- // }
- //
- // return 0;
- //}
- //函数模板
- //template<typename T>
- #include <stdio.h>
- #include <math.h>
- //反正切,知道两对边,求弧度(要自己转化成角度)
- /*int main(void)
- {
- double result;
- double x = 10.0, y = 10.0;
- result = atan2(y, x);
- printf("The arc tangent ratio of %lf is %.1lf\n", (y / x), result*180/3.1415926);
- return 0;
- }*/
- //#include <stdio.h>
- //#include <math.h>
- ////传入的参数为弧度
- //int main(void)
- //{
- // double result, x = 0.5;
- //
- // result = sin(x);
- // printf("The sin() of %lf is %lf\n", x, result);
- // return 0;
- //}
- //弧度转化角度:弧度*180/PI
- //角度转化弧度:角度*PI/180
- //#include <math.h>
- //#include <stdio.h>
- //const double PI=acos(-1.0);
- ////sin传入的参数的是弧度
- //void main()
- //{
- // int z=30;
- // double x = 10.0, y = 10.0;
- // double result;
- // //sin30结果
- // printf("sin(%d)=%.2lf\n",z,sin(2*PI*z/360.0));
- // result=atan2(y, x); //结果返回是弧度
- // printf("The arc tangent ratio of %lf is %.1lf\n", (y / x), result*180/PI);
- // //sin45的结果
- // printf("sin(%.0f)=%.2lf\n",result*180/PI,sin(result)); //注意不要用%d
- //}
- //桶排序思想
- //假如要排序的是数字是 2 4 5 5 5 8 8 9 1 1
- //#include<stdio.h>
- //#define length 10
- //int main()
- //{
- // //数组元素值全部初始化为0
- // int array[length]={0};
- // int i,j;
- // int n;
- // for(i=0;i<length;i++)
- // {
- // scanf("%d",&n);
- // array[n]++;
- // }
- // for (i = 0; i < length; i++)
- // {
- // for(j=0;j<array[i];j++)
- // printf("%d ",i);
- // }
- //
- // return 0;
- //}
- // Ba 2 Da 4 Ea 5 Eb 5 Ec 5 Ha 8 Hb 8 Ia 9 Aa 1 Ab 1
- //#include<stdio.h>
- //#define length 10
- //
- //struct node
- //{
- // char country[6]; //国家
- // int count; //金牌数
- //};
- //int main()
- //{
- // int i,j,n;
- // int array[10][10]={0}; //数组内的元素是结构体索引
- // int index[10]={0}; //存储每行队列(数组)内元素个数
- // struct node ary[length]={
- // {"Ba",2},{"Da",4},{"Ea",5},{"Eb",5},
- // {"Ec",5},{"Ha",8},{"Hb",8},{"Ia",9},
- // {"Aa",1},{"Ab",1}};
- // for(i=0;i<length;i++)
- // {
- // n=ary[i].count; //桶子编号
- // array[n][index[n]]=i; //存储结构体数组索引
- // index[n]++;
- // }
- // for(i=0;i<length;i++)
- // {
- // for(j=0;j<index[i];j++)
- // {
- // printf("%s %d\n",ary[array[i][j]].country,ary[array[i][j]].count);
- // }
- // }
- //}
- //#include<stdio.h>
- //
- //int main()
- // {
- // int nVar = 0x12345678;
- // int *pnVar = &nVar;
- // char *pcVar = (char*)&nVar;
- // short *psnVar = (short*)&nVar;
- // printf("%08x \r\n", *pnVar);
- // printf("%08x \r\n", *pcVar);
- // printf("%08x \r\n", *psnVar);
- // return 0;
- // }
- //拷贝构造函数
- // 04.cpp : Defines the entry point for the console application.
- //
- //#include "stdafx.h"
- #include "iostream"
- using namespace std;
- class CDog
- {
- public:
- unsigned int m_Weight;
- unsigned int m_Age;
- CDog(int weight,int age);
- CDog(int weight = );
- CDog(const CDog & theDog);
- void SetAge(unsigned int age);
- int GetAge ();
- ~CDog();
- };
- CDog::CDog(int weight,int age)
- {
- m_Weight = weight;
- m_Age = age;
- }
- CDog::CDog(int weight)
- {
- m_Weight = weight;
- }
- CDog::CDog(const CDog & theDog)
- {
- m_Weight = theDog.m_Weight;
- m_Age = theDog.m_Age;
- printf("Copy constructor is called.\n");
- }
- void CDog::SetAge(unsigned int age)
- {
- m_Age = age;
- }
- int CDog::GetAge ()
- {
- return m_Age;
- }
- CDog::~CDog()
- {
- }
- CDog CopyData(CDog m_dog)
- {
- return m_dog;
- }
- void test(CDog tmp)
- {
- }
- CDog test2()
- {
- CDog temp;
- cout<<"对象以值传递的方式从函数返回"<<endl;
- return temp;
- }
- int main(int argc, char* argv[])
- {
- CDog Example;
- cout<<"对象以值传递的方式传入函数参数"<<endl;
- test(Example);
- test2();
- //对象需要通过另外一个对象进行初始化
- //这里调用的是拷贝构造函数。而不是我们看到的赋值
- CDog test3 = Example;
- return ;
- }
浅拷贝与深拷贝
1.浅拷贝指的是只对对象中的数据成员进行简单的赋值。
2.默认拷贝构造函数执行的就是浅拷贝。
3.默认拷贝构造函数不会处理静态数据成员。
4.浅拷贝无法处理对象内的动态成员。
原因:浅拷贝仅仅是赋值,所以拷贝的对象的动态成员与原对象动态成员指向同一块内存,但是析构函数却会调用二次,
释放两次同一块内存,自然会出错。
5.深拷贝会在拷贝函数中为动态成员分配内存。
- //代码来自:
- //http://blog.csdn.net/lwbeyond/article/details/6202256 作者:lwbeyond
- #include "iostream"
- using namespace std;
- class Rect
- {
- public:
- Rect() // 构造函数,p指向堆中分配的一空间
- {
- p = new int();
- }
- ~Rect() // 析构函数,释放动态分配的空间
- {
- if(p != NULL)
- {
- delete p;
- }
- }
- private:
- int width;
- int height;
- int *p; // 一指针成员
- };
- int main()
- {
- Rect rect1;
- Rect rect2(rect1); // 复制对象
- return ;
- }
如果运行此程序,会出错。原因上面已经阐述。
修改成深拷贝:
- //代码来自:
- //http://blog.csdn.net/lwbeyond/article/details/6202256 作者:lwbeyond
- #include "iostream"
- using namespace std;
- class Rect
- {
- public:
- Rect() // 构造函数,p指向堆中分配的一空间
- {
- p = new int();
- }
- Rect(const Rect& r)
- {
- width = r.width;
- height = r.height;
- //p = new int(100); // 为新对象重新动态分配空间
- p = new int; // 为新对象重新动态分配空间
- *p = *(r.p);
- }
- ~Rect() // 析构函数,释放动态分配的空间
- {
- if(p != NULL)
- {
- delete p;
- }
- }
- private:
- int width;
- int height;
- int *p; // 一指针成员
- };
- int main()
- {
- Rect rect1;
- Rect rect2(rect1); // 复制对象
- return ;
- }
成功运行。
避免调用默认拷贝构造函数的方法:
声明一个私有拷贝构造函数。
拷贝构造函数可有一个或者多个。
下面来自博客: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++]的更多相关文章
- C++ 拷贝构造函数和赋值运算符
本文主要介绍了拷贝构造函数和赋值运算符的区别,以及在什么时候调用拷贝构造函数.什么情况下调用赋值运算符.最后,简单的分析了下深拷贝和浅拷贝的问题. 拷贝构造函数和赋值运算符 在默认情况下(用户没有定义 ...
- C++ 一个例子彻底搞清楚拷贝构造函数和赋值运算符重载的区别
class TestChild { public: TestChild() { x=; y=; printf("TestChild: Constructor be called!\n&quo ...
- C++ 为什么拷贝构造函数参数必须为引用?赋值构造函数参数也必须为引用吗?
之前写拷贝构造函数的时候,以为参数为引用,不为值传递,仅仅是为了减少一次内存拷贝.然而今天看到一篇文章发现自己对拷贝构造的参数理解有误. 参数为引用,不为值传递是为了防止拷贝构造函数的无限递归,最终导 ...
- C++拷贝构造函数
拷贝构造函数是一种特殊的构造函数,其定义为第一个参数为为本类型的一个引用或者是常引用,且无其它参数或者其它参数为默认值,例如下面的函数: X::X(const X&); X::X(X& ...
- PoEdu - C++阶段班【Po学校】- Lesson03-4_构造函数&赋值函数&拷贝构造函数&学习方式 - 第6天
PoEdu - C++阶段班[Po学校]- 第6天 课堂选择题目: 1 关于转换构造函数 ClassDemo demo = 1; 调用转换构造函数 2 关于拷贝赋值函数 demo =2; 首 ...
- C++拷贝构造函数(深拷贝,浅拷贝)
对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. #i ...
- C++ 拷贝构造函数 和 六大函数
1. C++什么时候会调用 拷贝构造函数? a.一个对象作为函数参数,以值传递的方式传入函数体: b.一个对象作为函数返回值,以值传递的方式从函数返回:(实际使用时,会被编译器优化掉) c.一个对象 ...
- 一个CString的实现 拷贝构造函数的应用
class CString { public: CString (char* s); CString(); ~CString(); private: char *str; int len; stati ...
- 【转】C++的拷贝构造函数深度解读,值得一看
建议看原帖 地址:http://blog.csdn.net/lwbeyond/article/details/6202256 一. 什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很 ...
- C++拷贝构造函数(深拷贝,浅拷贝)
http://www.cnblogs.com/BlueTzar/articles/1223313.html 对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; ...
随机推荐
- Linux学习《第四章shell脚本练习一》随堂练习(重要)
- Spring容器的创建原理
1.new ioc容器(AnnotationConfigApplicationContext 注解ioc) 2.refresh()方法调用 2.1 prepareRefresh()刷新前的预处理 a: ...
- 【ABP】从零开始学习ABP_入门介绍
本文介绍自己入坑ABP的过程,一些ABP的相关文章.QQ群,以及ABP Zero示例项目的运行. 背景 作为一个半路出家学习编程的新人,之前工作中也断断续续写过一些代码,但底层核心一直没机会学习,所以 ...
- Python基础笔记:list和tuple
list 与 tuple 就类似于C语言中的数组,list 与 tuple 的区别就是list 可修改,而tuple不可修改: list用法示例: >>> s=[] >> ...
- 使用docker快速体验kali linux
环境 运行在 64位 机器 企业版的 win10 系统 下载镜像 首先搜索docker download 去官网下载docker:https://www.docker.com/products/doc ...
- ng : File C:\Users\baron\AppData\Roaming\npm\ng.ps1 cannot be loaded because running
一. Windos PowerShell 选择 管理员身份运行二.set-ExecutionPolicy RemoteSigned 然后更改权限为A 三.get-ExecutionPolicy 查看当 ...
- JDK1.8 HashMap学习
1:源码分析 1.1:构造方法 public HashMap(int initialCapacity, float loadFactor) { ) throw new IllegalArgumentE ...
- Unity3d中渲染到RenderTexture的原理,几种方式以及一些问题
超级搬运工 http://blog.csdn.net/leonwei/article/details/54972653 ---------------------------------------- ...
- GWCTF 2019]我有一个数据库
0x00 知识点 phpMyadmin(CVE-2018-12613)后台任意文件包含漏洞 影响版本:4.8.0--4.8.1 payload:/phpmyadmin/?target=db_datad ...
- 2020/2/3 PHP代码审计之PHP伪协议
0x00 简介 开局一张图233 0x01 file://协议 说明: file:// 文件系统是 PHP 使用的默认封装协议,展现了本地文件系统.当指定了一个相对路径(不以/..\或 Windows ...