拷贝构造函数和赋值构造函数声明为私有的作用

2023-11-01

转载:http://blog.csdn.net/rabbit729/article/details/4000500

每个类只有一个赋值函数.

  由于并非所有的对象都会使用拷贝构造函数和赋值函数,程序员可能对这两个函数有些轻视。请先记住以下的警告,在阅读正文时就会多心:

  1.如果不主动编写拷贝构造函数和赋值函数,编译器将以“位拷贝”的方式自动生成缺省的函数。倘若类中含有指针变量,那么这两个缺省的函数就隐含了错误。以类String的两个对象a,b为例,假设a.m_data的内容为“hello”,b.m_data的内容为“world”。

  现将a赋给b,缺省赋值函数的“位拷贝”意味着执行b.m_data = a.m_data。这将造成三个错误:一是b.m_data原有的内存没被释放,造成内存泄露;二是b.m_data和a.m_data指向同一块内存,a或b任何一方变动都会影响另一方;三是在对象被析构时,m_data被释放了两次。

  2.拷贝构造函数和赋值函数非常容易混淆,常导致错写、错用。拷贝构造函数是在对象被创建时调用的,而赋值函数只能被已经存在了的对象调用。以下程序中,第三个语句和第四个语句很相似,你分得清楚哪个调用了拷贝构造函数,哪个调用了赋值函数吗?

String a(“hello”);
String b(“world”);
String c = a; // 调用了拷贝构造函数,最好写成 c(a);
c = b; // 调用了赋值函数

  本例中第三个语句的风格较差,宜改写成String c(a) 以区别于第四个语句。

  类String的拷贝构造函数与赋值函数:
  

// 拷贝构造函数

  String::String(const String &other)

  {

      // 允许操作other的私有成员m_data

      int length = strlen(other.m_data);

      m_data = new char[length+1];

      strcpy(m_data, other.m_data);

  }

  // 赋值函数

  String & String::operate =(const String &other)

  {

      // (1) 检查自赋值

      if(this == &other)

      return *this;

      // (2) 释放原有的内存资源

      delete [] m_data;

      // (3)分配新的内存资源,并复制内容

      int length = strlen(other.m_data);

      m_data = new char[length+1];

      strcpy(m_data, other.m_data);

      // (4)返回本对象的引用

      return *this;

  }

  类String拷贝构造函数与普通构造函数的区别是:在函数入口处无需与NULL进行比较,这是因为“引用”不可能是NULL,而“指针”可以为NULL。

  类String的赋值函数比构造函数复杂得多,分四步实现:

  (1)第一步,检查自赋值。你可能会认为多此一举,难道有人会愚蠢到写出 a = a 这样的自赋值语句!的确不会。但是间接的自赋值仍有可能出现,例如

  // 内容自赋值

  b = a;

  …

  c = b;

  …

  a = c;

  // 地址自赋值

  b = &a;

  …

  a = *b;

  也许有人会说:“即使出现自赋值,我也可以不理睬,大不了化点时间让对象复制自己而已,反正不会出错!”

  他真的说错了。看看第二步的delete,自杀后还能复制自己吗?所以,如果发现自赋值,应该马上终止函数。注意不要将检查自赋值的if语句

  if(this == &other)

  错写成为

  if( *this == other)

  (2)第二步,用delete释放原有的内存资源。如果现在不释放,以后就没机会了,将造成内存泄露。

  (3)第三步,分配新的内存资源,并复制字符串。注意函数strlen返回的是有效字符串长度,不包含结束符‘/0’。函数strcpy则连‘/0’一起复制。

  (4)第四步,返回本对象的引用,目的是为了实现象 a = b = c 这样的链式表达。注意不要将 return *this 错写成 return this 。那么能否写成return other 呢?效果不是一样吗?

  不可以!因为我们不知道参数other的生命期。有可能other是个临时对象,在赋值结束后它马上消失,那么return other返回的将是垃圾。

  偷懒的办法处理拷贝构造函数与赋值函数

  如果我们实在不想编写拷贝构造函数和赋值函数,又不允许别人使用编译器生成的缺省函数,怎么办?

  偷懒的办法是:只需将拷贝构造函数和赋值函数声明为私有函数,不用编写代码。

  例如:  

    class A

  {   …

      private:

      A(const A &a); // 私有的拷贝构造函数

      A & operate =(const A &a); // 私有的赋值函数

  };

  如果有人试图编写如下程序:

  A b(a); // 调用了私有的拷贝构造函数

  b = a; // 调用了私有的赋值函数

  编译器将指出错误,因为外界不可以操作A的私有函数。

  3.在编写派生类的赋值函数时,注意不要忘记对基类的数据成员重新赋值

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

拷贝构造函数和赋值构造函数声明为私有的作用 的相关文章

随机推荐

  • 为什么使用GB28181而不是直接rtsp拉流

    1 GB sip和rtsp 实际上 sip协议和rtsp协议大同小异 并没有什么本质上得不同 那为什么我们不使用rtsp 而转而使用GB28181国标得sip协议 原因是 使用得方向不同 我们使用rtsp拉流是作为客户端 这时摄像机是服务端
  • 【问题解决】partially initialized module ‘cv2‘ has no attribute

    使用 MMOCR 时报错 partially initialized module cv2 has no attribute 可能是 opencv 的版本问题 也可能是 opencv 和当前环境不能完全匹配的问题 可以使用下面的方法重新安装
  • 分享一个 ChatGPT可免费使用的AI助手

    现在 多种行业都已经开始广泛地采用聊天机器人ChatGPT 有一个与之相关的国内免费网站可以供大家使用 多御浏览器 这是一款安全快速 高效稳定的浏览器 该网站客户端软件中 有很多实用工具 其中之一就是当下非常流行的 ChatGPT 这对于开
  • python 更换pip安装源

    pip源 默认从国外源安装 安装速度比较慢 现在我们指定国内源安装源 阿里源 豆瓣源 Ubuntu源 1 指令配置源 pip3 install xlrd i https pypi tuna tsinghua edu cn simple 2
  • Qt - QSetting的使用

    欢迎转载 请注明出处 https blog csdn net qq 39453936 spm 1010 2135 3001 5343 原文链接 https blog csdn net qq 39453936 article details
  • Allegro快捷键

    env文件替换路径C Cadence SPB 16 6 share pcb text
  • mac启动pg数据库失败 “Is another postmaster (PID 370) running in data directory“

    解决办法 进入目录 usr local var postgres 删除文件 postmaster pid 启动pg命令 pg ctl D usr local var postgres l usr local var postgres ser
  • 挖矿病毒的特点

    挖矿病毒的特点 1 文件 定时任务删除失败 文件只读属性保护 2 文件 定时任务删完又出现 系统文件替换 下载进程残留 3 病毒进程刚刚删完又被拉起 恶意进程守护 4 主机严重卡顿但找不到挖矿进程 系统命令劫持 5 主机杀干净后一段时间又出
  • 【云原生之kubernetes】在kubernetes集群下的映射外部服务—Eendpoint

    云原生之kubernetes 在kubernetes集群下的映射外部服务 Eendpoint 一 Eendpoint介绍 1 endpoint简介 2 endpoint的使用 二 检查本地k8s状态 1 检查工作节点状态 2 检查系统pod
  • Modelsim、Matlab在远程桌面下打开的异常及处理

    此方法可以解决远程桌面下启动MATLAB时的License Manager Error 103错误 也能够解决远程桌面下启动modelsim的错误 方法如下 1 打开C Program Files MATLAB R2015b license
  • kafka基础介绍

    目录 前言 一 kafka架构 1 kafka基础架构 2 kafka多副本架构 二 kafka基础概念 1 produce 2 Consumer 3 Broker 4 Topic 5 Partition 6 Replicas 7 Offs
  • C++数据结构X篇_12_树的基本概念和存储

    学习二叉树之前先学习树的概念 文章目录 1 树的基本概念 1 1 树的定义 1 2 树的特点 1 3 若干术语 2 树的表示法 2 1 图形表示法 2 2 广义表表示法 3 树的存储 3 1 双亲表示法 保存父节点关系 3 2 孩子表示法
  • 伴随矩阵的特征值和特征向量

    结 论 伴 随 矩 阵 的 特
  • winsock

    今天上午学习了 winsock的使用的过程 现将学习的收获总结如下 Winsock的属性 1 Localport 设定本机的端口号 端口号从0 65536 其中1024一下一般为专用的端口 如21为ftp默认端口 80为http默认端口 2
  • 关于对CSDN这些技术博客类网站的一些个人看法

    今天这篇文章其实是自己的一个分享与感悟 分享一下自己从技术小白到有点小实力的这个过程中对自己帮助的一些技术博客类网站的看法 关于我为什么会想写这么一篇文章呢 起因是我有一次查CSDN网站时候 看到了一篇文章 第一眼看到这篇文章的时候我觉得首
  • Java多线程 - - -线程安全问题

    Java 多线程学习笔记 二 线程安全问题的出现 当一个进程中的多个线程共享资源或数据的时候 就会出现安全隐患 例如 三个售票窗口同时售票 如果没有进行线程安全的处理 则会出现重票 错票等线程安全问题 package com fff 实现R
  • Modbus协议介绍

    Modbus协议介绍 简介 Modbus是一种串行通信协议 是Modicon公司 现在的施耐德电气Schneider Electric 于 1979年为使用可编程逻辑控制器 PLC 通信而发表 Modbus 已经成为工业领域通信协议的业界标
  • JDBC数据库驱动的下载、安装与连接

    1 常用的数据库驱动下载 使用JDBC操作数据库 需要使用数据库厂商提供的驱动程序 通过驱动程序可以与数据库进行交互 1 1 常用的数据库厂商驱动下载地址 1 1 1 MySQL数据库 https dev mysql com downloa
  • Pytorch基于DDPM+InceptionNext+数据增强的图像分类(一)

    项目简介 本项目旨在通过使用深度学习技术实现对图像进行分类 我采用了DDPM Deep Dynamic Probabilistic Modeling 和InceptionNext两个模型的结合 以提高图像分类的准确性和性能 同时 我还使用了
  • 拷贝构造函数和赋值构造函数声明为私有的作用

    转载 http blog csdn net rabbit729 article details 4000500 每个类只有一个赋值函数 由于并非所有的对象都会使用拷贝构造函数和赋值函数 程序员可能对这两个函数有些轻视 请先记住以下的警告 在