C++之拷贝函数

拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类型的一个引用变量,该参数是const类型,不可变的。例如:类X的拷贝构造函数的形式为X(X& x)。

以下情况都会调用拷贝构造函数:
一个对象以值传递的方式传入函数体
一个对象以值传递的方式从函数返回
一个对象需要通过另外一个对象进行初始化。

如果在类中没有显式地声明一个拷贝构造函数,那么,编译器将会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝。位拷贝又称浅拷贝,后面将进行说明。

自定义拷贝构造函数是一种良好的编程风格,它可以阻止编译器形成默认的拷贝构造函数,提高源码效率。

浅拷贝和深拷贝

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

  深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。
  
深拷贝和浅拷贝的定义可以简单理解成:如果一个类拥有资源(堆,或者是其它系统资源),当这个类的对象发生复制过程的时候,这个过程就可以叫做深拷贝,反之对象存在资源,但复制过程并未复制资源的情况视为浅拷贝。

浅拷贝资源后在释放资源的时候会产生资源归属不清的情况导致程序运行出错。

代码实现:
拷贝构造:

#include <stdio.h>class Test6_1
{
public:Test6_1 (int a){m_a = a;printf ("普通构造函数\n");}// 拷贝构造Test6_1(const Test6_1 &obj){// m_a = obj.m_a;m_a = -100;printf ("拷贝构造被调用\n");}~Test6_1(){printf ("***********析构函数被调用: m_a = %d\n", m_a);}void print(){printf ("a = %d\n", m_a);}
private:int m_a;
};// void test(Test6_1 &t)
void test(Test6_1 t)
{t.print();
}Test6_1 test6_1()
{Test6_1 t(10);return t;
}// 函数返回值是一个对象
int main6_2()
{// 一个函数返回一个对象的时候会创建一个匿名对象,拿返回的那个对象// 对匿名对象进行初始化,会调用拷贝构造// 如果没有去接收函数的返回值的话,匿名对象会立马被销毁// test6_1();// 如果用一个对象去接收函数的返回值,先用函数返回的对象去初始化// 匿名对象,调用一次拷贝构造,然后拿新的对象的名字去命名这个匿名对象// 匿名对象从无名转成有名// Test6_1 t1 = test6_1();Test6_1 t2(10);// 用函数返回的对象对匿名对象进行初始化,调用拷贝构造// 用匿名对象对  t2  进行赋值,调用 赋值运算符  = t2 = test6_1();// 初始化、构造、赋值int a;   // 定义变量int b = 20;  // 初始化a = 10;  // 赋值printf ("-------------------------\n");return 0;
}int main6_1()
{// 1、直接初始化Test6_1 t1(10);
#if 0Test6_1 t2(t1);    // 拿 t1 取初始化 t2// 2、等于号Test6_1 t3 = t1;t3.print();
#endif  // 3、当对象作为函数参数传递的时候会调用拷贝构造test(t1);return 0;
}

默认构造函数:

#include <stdio.h>class Test7_1
{
public:Test7_1(){}Test7_1(int a){m_a = a;}void print (){printf ("m_a = %d\n", m_a);}
private:int m_a;
};// 如果类中没有定义任何构造函数,编译器会自动生成一个无参构造函数,没有做任何事情
// 如果写了构造函数,编译器将不再提供默认的无参构造函数
// 如果还想进行无参构造,需要显示定义无参构造函数// 如果没有定义拷贝构造函数,编译器会自动生成一个拷贝构造函数,
// 会做普通类型数据的复制// 还会生成一个默认的 析构函数 
class Test7_2
{
#if 0Test7_2() {}Test7_2(const Test7_2 &obj) {}~Test7_2(){};
#endif
};int main7_1()
{Test7_1 b;Test7_1 a(10);Test7_1 c = a;a.print();c.print();return 0;
}

深拷贝和浅拷贝:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>// 浅拷贝:在拷贝指针的时候只是拷贝了地址,不会进行空间的复制
class Test8_1
{
public:Test8_1(int id, char *name){m_id = id;m_name = (char *)malloc(sizeof(char)*20);strcpy (m_name, name);}~Test8_1(){if (m_name != NULL){free (m_name);m_name = NULL;}printf ("析构被调用**********\n");}void print(){printf ("id = %d, name = %s\n", m_id, m_name);}
private:int m_id;
//  char m_name[20];char *m_name;
};// 深拷贝
class Test8_2
{
public:Test8_2(int id, char *name){m_id = id;m_name = (char *)malloc(sizeof(char)*20);strcpy (m_name, name);}// 自己写拷贝构造函数,避免浅拷贝Test8_2(const Test8_2 &obj){m_id = obj.m_id;m_name = (char *)malloc(sizeof(char)*20);strcpy (m_name, obj.m_name);}~Test8_2(){if (m_name != NULL){free (m_name);m_name = NULL;}printf ("析构被调用**********\n");}void print(){printf ("id = %d, name = %s\n", m_id, m_name);}
private:int m_id;char *m_name;
};class Test8_3
{
private:// 将拷贝构造写成私有的函数,只需声明,不需要实现Test8_3(const Test8_3 &ibj);public:Test8_3(int a){m_a = a;}private:int m_a;
};
int main8_3()
{Test8_3 t(10);// Test8_3 t1 = t;return 0;
}int main8_2()
{Test8_2 t1(10, "wang");t1.print();// 调用自己写的拷贝构造函数,进行深拷贝Test8_2 t2 = t1;t2.print();return 0;
}int main8_1()
{Test8_1 t1(10, "wang");t1.print();// 调用默认的拷贝构造函数Test8_1 t2 = t1;//t2.print();return 0;
}

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

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

相关文章

spring Boot 学习(七、Spring Boot与开发热部署)

一、热部署在开发中我们修改一个Java文件后想看到效果不得不重启应用&#xff0c;这导致大量时间 花费&#xff0c;我们希望不重启应用的情况下&#xff0c;程序可以自动部署&#xff08;热部署&#xff09;。有以下四 种情况&#xff0c;如何能实现热部署。•1、模板引擎 – 在…

解决: Cannot find module ‘webpack-cli/bin/config-yargs‘、Error: Cannot find module ‘webpack-cli‘

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 npm 、cnpm 、node、vue 全都装上了&#xff0c;就是 webpack 装不上&#xff01;&#xff01; 最后我把整个服务器还原为初始设置了&…

路由器和交换机的区别详解

很多人对路由器和交换机混为一谈&#xff0c;甚至搞不清楚路由器和交换机有什么区别&#xff0c;有的用户还认为是一样的功能&#xff0c;看名字就知道是两种不同的产品&#xff0c;功能虽然有些类似&#xff0c;但绝对不会完全相同&#xff0c;否则就没有必要用两个全面不同的…

C++之构造函数和析构函数强化

构造与析构调用顺序: #include <stdio.h>class Test9_1 { public:Test9_1 (int a){m_a a;printf ("9_1 1111111111111111111构造函数....a: %d\n", a);}// 析构的顺序和构造的顺序相反&#xff0c;先构造的后析构~Test9_1(){printf ("9_1 1111111111111…

Oracle的逆向工程generatorConfig

<?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <ge…

最简单、图解:阿里云服务器上装 Docker 、 CentOS上 docker安装(3分钟装完)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 // 为了装 vue 的 webpack &#xff0c;我把整个服务器重置了。docker 也没有了&#xff0c;只好重新装 docker ... 1. 准备工作 yum …

C++之对象的动态建立和释放

new和delete的用法&#xff1a; 1&#xff09;在软件开发过程中&#xff0c;常常需要动态地分配和撤销内存空间&#xff0c;例如对动态链表中结点的插入与删除。在C语言中是利用库函数malloc和free来分配和撤销内存空间的。C提供了较简便而功能较强的运算符new和delete来取代m…

7.11牛客题(指针)

今天在牛客做错了一道题&#xff0c;在此写下感触题目如下&#xff1a;若有说明:int i, j2,*p&i;,则能完成 ij 赋值功能的语句是&#xff08;B&#xff09;。A i*p; B *p*&j; C i&j; D i**p; 分析&#xff1a;题目中&#xff0c;p指针指向i的地址&#xff0c;A选项…

gpu简介

GPU英文全称Graphic Processing Unit&#xff0c;中文翻译为“图形处理器”。GPU是相对于CPU的一个概念&#xff0c;由于在现代的计算机中&#xff08;特别是家用系统&#xff0c;游戏的发烧友&#xff09;图形的处理变得越来越重要&#xff0c;需要一个专门的图形的核心处理器…

WM有约(五):部署应用程序

WM有约&#xff08;五&#xff09;&#xff1a;部署应用程序 Written by Allen Lee 创建安装包 创建一个新的项目&#xff0c;用来部署Windows Mobile应用程序的项目模板是Other Project Types\Setup and Deployment下的Smart Device CAB Project&#xff1a; 图 1 输入项…

“ 我亦想望,如池鱼悠悠 ... “

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 // 闹钟响了&#xff0c;起床&#xff0c;洗漱完毕&#xff0c;背上电脑出门&#xff0c;到公司打卡 8&#xff1a;20 。 " 我亦想…

C++之静态成员变量和静态成员函数

静态成员变量 关键字 static 可以用于说明一个类的成员&#xff0c; 静态成员提供了一个同类对象的共享机制 把一个类的成员说明为 static 时&#xff0c;这个类无论有多少个对象被创建&#xff0c;这些对象共享这个 static 成员 静态成员局部于类&#xff0c;它不是对象成…

熄火/死火

定义 当反应器正在以显著的反应速率进行操作时&#xff0c;若降低进料入口的温度&#xff0c;使它达到多重态区域的下限&#xff0c;反应速度会突然大幅度下降&#xff0c;反应基本上停止。这个现象称为熄灭。相应的入口温度称为熄灭点。一般指的是汽车熄火。发生原因 有…

H3C 以太网集线器

转载于:https://www.cnblogs.com/fanweisheng/p/11169349.html

解决: WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 问题描述&#xff1a;阿里云服务器 磁盘初始化之后用 git-bash ssh rootxx.xx.xx.xx 方式登陆服务器&#xff0c;报错如下。 WARNIN…

C++之面向对象模型

C对象模型可以概括为以下2部分&#xff1a; 1. 语言中直接支持面向对象程序设计的部分&#xff0c;主要涉及如构造函数、析构函数、虚函数、继承&#xff08;单继承、多继承、虚继承&#xff09;、多态等等。 2. 对于各种支持的底层实现机制。 在c语言中&#xff0c;“数据”…

netty接收大文件的方法

参考:http://blog.csdn.net/linuu/article/details/51371595 https://www.jianshu.com/p/a0a51fd79f62 netty默认是只能接收1024个字节&#xff0c;但是我们要传输大文件怎么办&#xff1f; 上代码&#xff1a; 改之后服务端&#xff1a; package server;import io.netty.boots…

制动失灵

定义 制动过程中&#xff0c;由于制动器某些零部件的损坏或发生故障&#xff0c;使运动部件(或运动机械)不能保持停止状态或不能按要求停止运动的现象。制动失灵的原因 制动失灵的关键在于制动系统无法对汽车施加足够的制动力&#xff0c;包括制动液管路液位不足或进入…

webpack 入门,说一下那些不入流的知识点、module.exports{ } 中配置说明

先说说Vue-Cli&#xff08;Vue项目脚手架&#xff09; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 关于它能干什么&#xff0c;就不再赘述了&#xff0c;我们主要谈谈生成的与webp…

myeclipse2013 jad反编译插件安装

https://blog.csdn.net/zhenshixian88/article/details/26454319 1. 下载插件工具 http://download.csdn.net/detail/zwj_lmss/6697259 2. 里面有两个文件 1).JAD.EXE随便找个地方丢进去(我是随便放哪边的,不过有的人有问题,最后放在了jdk的bin下面.可能他们没有配置环境变量);…