当前位置: 首页 > news >正文

C++对象的赋值与复制复制构造函数(指针数据成员)

一、对象的赋值

同类对象之间可以相互赋值,对象赋值的一般形式:
对象名2 = 对象名1;
原理是,赋值运算符的重载。仅赋值,因此赋值前,需要先定义并初始化对象2

对象的赋值针对指对象中所有数据成员的值
对象的赋值只对其中的数据成员赋值,不涉及成员函数。

#include <iostream>
#include <sstream>
using namespace std;class Student
{
public:Student(){num = 0;}Student(int n, string na, char s){num = n;name = na;sex = s;}void showinf( ){cout<<"num:"<<num<<"\tname:"<<name<<"\tsex:"<<sex<<endl;}     
private:int num;string name;char sex;
};int main()
{Student stud1(101,"LL",'m');//定义并初始化stud1,调用Student(int n, string na, char s);Student stud2;      //定义并初始化stud2,调用Student();stud1.showinf();stud2.showinf();stud2=stud1;        //赋值运算符重载,仅赋值操作,因此之前应先定义并初始化stud2stud2.showinf();return 0;
}

二、对象的复制

用已有的对象克隆出一个新对象,对象复制的一般形式为:
类名 对象2(对象1);   
原理:调用了编译系统提供的默认复制构造函数

Student∷Student(const Student& obj)    //默认构造函数
{num=obj.num;name=obj.name;sex=obj.sex;
}


既定义又复制,定义的同时执行复制对象操作!不需要提前定义和初始化对象2

等价形式:类名 对象2=对象1;(注:注意区分对象赋值操作)

#include <iostream>
#include <sstream>
using namespace std;class Student
{
public:Student(int n, string na, char s){num = n;name = na;sex = s;}void showinf( ){cout<<"num:"<<num<<"\tname:"<<name<<"\tsex:"<<sex<<endl;}     
private:int num;string name;char sex;
};int main()
{Student stud1(101,"LL",'m');Student stud2(stud1);         //等价于 Student stud2 =stud1;  既是定义,又是复制 == 定义&复制stud2.showinf();return 0;
}

三、复制构造函数

1、什么时候需要通过复制构造函数对对象进行复制?

(1)新建立一个对象时:直接利用复制构造函数进行定义和初始化Box box2(box1);
(2)当函数的参数为类的对象:调用函数时,将实参对象完整地传递给形参,通过调用复制构造函数来建立一个实参的拷贝;

void fun(Box b){ }int main( )
{Box box1(12,15,18);fun(box1);return 0;
}

(3)函数的返回值是类的对象:在函数调用完毕,将函数中的对象复制一个临时对象并传给该函数的调用处。

Box fun( )
{Box box1(12,15,18);return box1;
}
int main( )
{Box box2;box2=fun( );
}

2、复制构造函数的形式

复制构造函数的定义形式如下:

类名(const 类名&对象名)

Time(const Time & object);

3、浅复制

浅复制是指,使用默的复制方式{类名 对象2(对象1);或 类名 对象2 = 对象1}方式,复制数据成员的方式(此种方式无法传递指针数据成员)。

例1 当数据成员不包含指针时,此种复制方式不会出现问题。
#include <iostream>
using namespace std;
class Test
{
private:int x;
public:Test(int n) {x=n; }Test(const Test& obj){x=obj.x; }//复制构造函数void show (){cout<<x<<endl;}
};int main()
{Test test1(100);Test test2(test1); //对象复制形式一,调用复制构造函数Test(const Test& obj)Test test3=test1;  //对象复制形式二,调用复制构造函数Test(const Test& obj)test2.show();test3.show();return 0;
}

例2 当数据成员包含指针时,此复制方式会由于指针的传递出现异常
#include <iostream>
using namespace std;
class Test
{
private:int x;char *pcr;              //定义字符指针,可指向字符串或字符数组
public:Test(int n, char* c)    //初始化构造函数!!!{x=n;strcpy(pcr, c);     //错误点:这是一个野指针!!!!(但不是根源,根源是复制的方式不对)}Test(const Test& obj)   //复制构造函数!!!{x=obj.x;strcpy(pcr, obj.pcr);}void show (){cout<<"x:"<<x<<"\t pcr:"<<pcr<<endl;}
};int main()
{Test test1(100,'L');        //初始化对象test1Test test2(test1);          //对象复制形式一,调用复制构造函数Test(const Test& obj)Test test3=test1;           //对象复制形式二,调用复制构造函数Test(const Test& obj)test2.show();test3.show();return 0;
}

编译会报错。

4、深复制

深复制的目的:先给包含指针的数据成员分配空间,然后再去复制(避免了指针数据成员存在野指针情况)。

例3  在复制构造函数中预先为指针数据成员分配空间(在析构函数中释放空间)
#include <iostream>
using namespace std;
class Test
{
private:int x;char *pcr;               //定义字符指针,可指向字符串或字符数组       
public:Test(int n, char* c)     //初始化构造函数{x=n;int m = strlen(c)+1; //C语言中的字符串结尾\0,因此长度+1pcr = new char[m];   //为指针成员分配空间,避免野指针strcpy(pcr, c);     }Test(const Test& obj)   //复制构造函数{x=obj.x;int m = strlen(obj.pcr)+1;pcr = new char[m];          //为指针成员分配空间,避免野指针strcpy(pcr, obj.pcr);}~Test(){delete pcr;}            //由于构造函数中分配了空间,因此必须在析构函数中释放void show (){cout<<"x:"<<x<<"\t pcr:"<<pcr<<endl;}
};int main()
{Test test1(100,"Alibaba");  //初始化对象test1Test test2(test1);          //对象复制形式一,调用复制构造函数Test(const Test& obj)Test test3=test1;           //对象复制形式二,调用复制构造函数Test(const Test& obj)test2.show();test3.show();return 0;
}

例5 在复制构造函数中对指针数据成员直接传递【非常危险】
#include <iostream>
using namespace std;
class Test
{
private:int x;char *pcr;              //定义字符指针,可指向字符串或字符数组
public:Test(int n, char* c)     //初始化构造函数{x=n;pcr = c;            //!直接传递指针地址(貌似对,一定有机会错!)}Test(const Test& obj)   //复制构造函数{x=obj.x;pcr = obj.pcr;}void show (){cout<<"x:"<<x<<"\t pcr:"<<pcr<<endl;}
};int main()
{Test *pt1;pt1 = new Test(100,"GW");Test test2(*pt1);Test test3 = (*pt1);test2.show();test3.show();delete pt1;test2.show();test3.show();return 0;
}

注意:虽然通过传递指针的方式,实现了对象的复制。但是当Test *pt1被释放掉时,由pt1复制产生的test2和test3的数据成员中的指针数据成员,所指向的内存空间可能不变,也可能改变。
上图程序运行的结果是:释放后此段内存空间没变,但实际程序运行中则不一定。
所以,直接传递指针的方式非常危险!

相关文章:

C++对象的赋值与复制复制构造函数(指针数据成员)

一、对象的赋值 同类对象之间可以相互赋值&#xff0c;对象赋值的一般形式&#xff1a;对象名2 对象名1; 原理是&#xff0c;赋值运算符的重载。仅赋值&#xff0c;因此赋值前&#xff0c;需要先定义并初始化对象2。 对象的赋值针对指对象中所有数据成员的值&#xff1b; 对…...

Coding Caprice - monotonic stack2

42. 接雨水 class Solution { public:int trap(vector<int>& height) {stack<int> sh;int out 0;for(int i0; i<height.size(); i){while(!sh.empty() && height[sh.top()]<height[i]){int bo height[sh.top()];sh.pop();if(sh.empty()){brea…...

Spring Mvc面试题(常见)

1 Spring MVC的执行流程 用户发起请求,请求先被Servlet拦截以后,转发给SpringMVC框架SpringMVC 里面的DispatcherServlet(核心控制器) 接收到请求,并转发给HandlerMappingHandlerMapping负责解析请求,根据请求信息和配置信息找到匹配的Controller类(当这里有配置拦截器,会…...

opencv # Sobel算子、Laplacian算子、Canny边缘检测、findContours、drawContours绘制轮廓、外接矩形

一、Sobel算子 案例图片 cv2.Sobel(src, ddepth, dx, dy, ksize3, scale1, delta0, borderTypeNone) 功能&#xff1a;用于计算图像梯度&#xff08;gradient&#xff09;的函数 参数&#xff1a; src: 输入图像&#xff0c;它应该是灰度图像。 ddepth: 输出图像的所需深度&am…...

Neo4j插入数据逐级提升速度4倍又4倍

语雀版&#xff1a;https://www.yuque.com/xw76/back/dtukgqfkfwg1d6yo 目录 背景介绍初始方案Node()创建事务批量提交记录Node是否存在生成Cypher语句执行数据库参数优化切换成85k个三元组测试建索引&#xff08;很显著&#xff01;&#xff01;&#xff01;&#xff09;MATCH…...

C++特殊类设计(单例模式等)

目录 引言 1.请设计一个类&#xff0c;不能被拷贝 2. 请设计一个类&#xff0c;只能在堆上创建对象 为什么设置实例的方法为静态成员呢 3. 请设计一个类&#xff0c;只能在栈上创建对象 4. 请设计一个类&#xff0c;不能被继承 5. 请设计一个类&#xff0c;只能创建一个对…...

J8学习打卡笔记

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 Inception v1算法实战与解析 导入数据数据预处理划分数据集搭建模型训练模型正式训练结果可视化详细网络结构图个人总结 import os, PIL, random, pathlib imp…...

前端学习-操作元素内容(二十二)

目录 前言 目标 对象.innerText 属性 对象.innerHTML属性 案例 年会抽奖 需求 方法一 方法二 总结 前言 曾经沧海难为水&#xff0c;除却巫山不是云。 目标 能够修改元素的文本更换内容 DOM对象都是根据标签生成的,所以操作标签,本质上就是操作DOM对象&#xff0c;…...

【踩坑】pip离线+在线在虚拟环境中安装指定版本cudnn攻略

pip离线在线在虚拟环境中安装指定版本cudnn攻略 在线安装离线安装Windows环境&#xff1a;Linux环境&#xff1a; 清华源官方帮助文档 https://mirrors.tuna.tsinghua.edu.cn/help/pypi/ 标题的离线的意思是先下载whl文件再安装到虚拟环境&#xff0c;在线的意思是直接在当前虚…...

golang操作sqlite3加速本地结构化数据查询

目录 摘要Sqlite3SQLite 命令SQLite 语法SQLite 数据类型列亲和类型——优先选择机制 SQLite 创建数据库SQLite 附加数据库SQLite 分离数据库 SQLite 创建表SQLite 删除表 SQLite Insert 语句SQLite Select 语句SQLite 运算符SQLite 算术运算符SQLite 比较运算符SQLite 逻辑运算…...

vllm加速(以Qwen2.5-7B-instruction为例)与流式响应

1. vllm介绍 什么是vllm? vLLM 是一个高性能的大型语言模型推理引擎&#xff0c;采用创新的内存管理和执行架构&#xff0c;显著提升了大模型推理的速度和效率。它支持高度并发的请求处理&#xff0c;能够同时服务数千名用户&#xff0c;并且兼容多种深度学习框架&#xff0c;…...

WordPress弹窗公告插件-ts小陈

使用效果 使用后网站所有页面弹出窗口 插件特色功能 设置弹窗公告样式&#xff1a;这款插件可展示弹窗样式公告&#xff0c;用户点击完之后不再弹出&#xff0c;不会频繁打扰用户。可设置弹窗中间的logo图&#xff1a;这款插件针对公告图片进行独立设置&#xff0c;你可以在设…...

【ELK】容器化部署Elasticsearch1.14.3集群【亲测可用】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1. 部署1.1 单节点1.2 新节点加入集群1.3 docker-compose部署集群 1. 部署 按照官网流程进行部署 使用 Docker 安装 Elasticsearch |Elasticsearch 指南 [8.14] |…...

[SAP ABAP] ALV状态栏GUI STATUS的快速创建

使用事务码SE38进入到指定程序&#xff0c;点击"显示对象列表"按钮 鼠标右键&#xff0c;选择"GUI状态" 弹出【创建状态】窗口&#xff0c;填写状态以及短文本描述以后&#xff0c;点击按钮 点击"调整模板"&#xff0c;复制已有程序的状态栏 填…...

【Linux】NET9运行时移植到低版本GLIBC的Linux纯内核板卡上

背景介绍 自制了一块Linux板卡(基于全志T113i) 厂家给的SDK和根文件系统能够提供的GLIBC的版本比较低 V2.25/GCC 7.3.1 这个版本是无法运行dotnet以及dotnet生成的AOT应用的 我用另一块同Cortex-A7的板子运行dotnet的报错 版本不够&#xff0c;运行不了 而我的板子是根本就识…...

深入浅出支持向量机(SVM)

1. 引言 支持向量机&#xff08;SVM, Support Vector Machine&#xff09;是一种常见的监督学习算法&#xff0c;广泛应用于分类、回归和异常检测等任务。自1990年代初期由Vapnik等人提出以来&#xff0c;SVM已成为机器学习领域的核心方法之一&#xff0c;尤其在模式识别、文本…...

Vue脚手架相关记录

脚手架 安装与配置 安装node node -> 16.20.2 切换淘宝镜像 npm install -g cnpm -registryhttp://registry.npm.taobao.orgnpm config set registry http://registry.npm.taobao.org/使用了第二个,下一步才有用 安装vue npm install -g vue/clivscode中不给运行vue解…...

基于Docker的Minio分布式集群实践

目录 1. 说明 2. 配置表 3. 步骤 3.1 放行服务端口 3.2 docker-compose 编排 4. 入口反向代理与负载均衡配置 4.1 api入口 4.2 管理入口 5. 用例 6. 参考 1. 说明 以多节点的Docker容器方式实现minio存储集群&#xff0c;并配以nginx反向代理及负载均衡作为访问入口。…...

Scala 的迭代器

迭代器定义&#xff1a;迭代器不是一种集合&#xff0c;它是一种用于访问集合的方法。 迭代器需要通过集合对应的迭代器调用迭代器的方法来访问。 支持函数式编程风格&#xff0c;便于链式操作。 创建一个迭代器&#xff0c;相关代码如下&#xff1a; object Test {def mai…...

vue实现文件流形式的导出下载

文章目录 Vue 项目中下载返回的文件流操作步骤一、使用 Axios 请求文件流数据二、设置响应类型为 ‘blob’三、创建下载链接并触发下载四、在 Vue 组件中集成下载功能五、解释与实例说明1、使用 Axios 请求文件流数据&#xff1a;设置响应类型为 blob&#xff1a;创建下载链接并…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...

LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用

中达瑞和自2005年成立以来&#xff0c;一直在光谱成像领域深度钻研和发展&#xff0c;始终致力于研发高性能、高可靠性的光谱成像相机&#xff0c;为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...