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

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++]的更多相关文章

  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. symbol数据类型

    symbol声明的类型独一无二 概念:表示独一无二的值,永远不相等 s1 = Symbol() s2 = Symbol() s1 !== s2 基本使用: 通过Symbol函数生成,得到一个symbo ...

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

  3. 【linux】linux系统安全设置

    1.下载安装安全软件 2.取消Telnet登录采用SSH方式并更改ssh服务端远程登录的配置 1)Telnet登录协议是明文不加密不安全,所以采用更安全的SSH协议. 2)更改ssh服务端远程登录相关 ...

  4. linux下nginx的安装和配置

    准备目录 [root@sqh ~]# mkdir /usr/local/nginx [root@sqh ~]# cd /usr/local/nginx 添加一些支持和依赖 1.安装gcc 安装redi ...

  5. node.js - 定义全局变量

    1,定义全局变量 app.set('name','八戒') 2,获取全局变量 app.get('name')

  6. Windows10 网络图标消失 连接不上网络 的解决方法

    [背景]电脑win10的,下载一个软件重启之后网络图标消失,并且无法联网. 参照此解决方法: 原因: [Windows Event Log]服务对应的注册表出现问题,导致无法正常启动,进而导致一些依赖 ...

  7. Vulkan SDK 之 DrawCube

    Waiting for a Swapchain Buffer Beginning the Render Pass Bind the Pipeline Bind the Descriptor Sets ...

  8. 《新标准C++程序设计》3.1.4-3.2(C++学习笔记6)

    1.类型转换构造函数 (1)定义 只有一个参数,而且不是复制构造函数的构造函数,一般就可以看作是转换构造函数. 当需要的时候,编译系统会自动调用转换构造函数,建立一个无名的临时对象(或临时变量). ( ...

  9. Docker 容器(container)

    版权所有,未经许可,禁止转载 章节 Docker 介绍 Docker 和虚拟机的区别 Docker 安装 Docker Hub Docker 镜像(image) Docker 容器(container ...

  10. java反射的认知和学习

    1.学习了Class对象,Filed对象(对应数据),Method对像(对应函数),Constructor对象(对应构造函数). 2.Declared可用于获取私有的数据和方法,但是打印得使用setA ...