构造函数和拷贝构造函数和移动构造函数的区别和使用

C++ 构造函数 C++中的构造函数、拷贝构造函数、移动构造函数详解。 阅读详情


以C++中的类类型来说明

源码

class Moveable
{

public:
	Moveable() : i(new int(3)){ //构造函数
		cout << "构造函数" << endl; 
	};
	~Moveable(){//析构函数
		delete i;//这里也没有必要判断i是否为空指针,然后再执行delete i,因为delete 一个指向空地址的指针变量 这里也不会报错,delete命令底层有优化。
		i = nullptr;//这里没必要把i置为空指针,因为i是对象中的非静态成员变量,对象生命周期结束后指针变量i生命周期也随着结束了。
	};
	Moveable(const Moveable & m) : i(new int(*m.i)){//拷贝构造函数
		cout << "调用拷贝构造函数" << endl;
	};
	Moveable(Moveable && m) : i(m.i){//移动构造函数
		cout << "调用移动构造函数" << endl;
		m.i = nullptr; 
	};
	int* i;
};

构造函数

构造函数,不显示的在类中写出来,会有隐式的构造函数。如:Moveable(){};什么参数都不需要传递。对象中的属性都是按照随机给值的。这样非常危险。所以一般都
会显示的重写构造函数,并在构造函数中初始化成员变量。构造函数支持重载。
什么时候会触发构造函数呢?
当创建对象时会自动触发调用构造函数。例如:Moveable m;//会触发调用构造函数

拷贝构造函数

拷贝构造函数,不显示的在类中写出来,会有隐式的拷贝构造函数。如:
Moveable(const Moveable & m) : i(m.i)){ };
拷贝何时会被触发调用呢。
Moveable m;//会触发调用构造函数
Moveable m1(m);//m是一个左值,不管编译器有没有做优化,都会调用拷贝构造函数
也就是根据一个已有的对象来生成另一个对象时,会触发拷贝构造函数。

浅拷贝

使用隐式拷贝构造函数,会产生浅拷贝问题,即新对象和旧对象中的指针成员 i都指向同一块堆内存,当这两个对象,其中一个释放内存时,会调一次delete i。
而另一个对象在释放内存时,也会调一次delete i。会产生同一个堆内存,被释放两次的情况,这种情况会使程序发生错误。
当第一次执行delete i 后,另一个对象中的指针变量i,就变成的悬空指针。也就是指针指向的内存已被释放了(不能再访问了)。
隐式拷贝构造函数就是 浅拷贝构造函数。为避免这种情况一般就需要重写拷贝构造函数。

深拷贝

针对以上隐式拷贝构造函数,带来的浅拷贝的问题。需要深拷贝来解决。
如:
Moveable(const Moveable & m) : i(new int(*m.i)){…拷贝操作…};
就是在拷贝的过程中,给新对象的指针成员属性重新分配一块堆内存,然后在 函数体内,把旧对象指针成员i指向的堆内存中的内容,拷贝一份到新对象指针成
员所指向的堆内存中。这样就解决了浅拷贝带来的悬空指针的问题。

移动构造函数

移动构造函数 是C++11中引入的一种新式构造函数,移动构造函数没有隐式的。想使用时,必须显示的在类中定义移动构造函数。
移动构造函数的形参类型是右值引用类型(也是C++11新出现的一个引用类型 例如: T &&)
例如:
Moveable(Moveable && m) : i(m.i){
m.i = nullptr;//移动语义
};
Moveable &&:就是一个右值引用类型,其实它在操作数据时,和 左值引用(Moveable &) 没啥区别,都表示要引用的对象的别名。
左值引用类型:用来引用左值的。
右值引用类型:用来引用右值的。

移动构造函数出现的意义是什么呢?
移动构造函数出现的意义就是在进行数据拷贝是,不想发生深拷贝那样的操作,如果指针成员i指向的那块堆内存内容特别大,那么进行深拷贝时,效率很低。而选择使用隐式拷贝构造函数 又会造成 上面所说的悬空指针的问题。
其实这里的移动构造函数可以看成是一个浅拷贝构造函数。因为重写了隐式的拷贝构造函数,那么类中就不在提供隐式的浅拷贝构造函数了。
所以在存在深拷贝构造函数的情况下,还想使用浅拷贝构造函数,又想避免浅拷贝带的悬空指针问题。那么移动构造函数就横空出世了。
移动构造函数和显示的深拷贝构造函数是可以共存的。
移动构造函数与默认的浅拷贝构造函数不同的地方,除了参数类型不一样外(一个是左值引用类型,一个是右值引用类型)。关键的区别在函数体内的移动语义。
移动构造函数和浅拷贝构造函数 都是在窃取别人的内容。
分析一下:移动构造函数的执行。首先接收一个右值,然后赋值给右值引用类型变量 m, 把旧对象指针i赋值给新对象的指针i。此时新对象的成员属性指针i也指向了旧对象的成员属性i所指向的那块堆内存。然后在函数体,把旧对象的属性指针i置为空指针。这样在旧对象生命周期结束时,触发析构函数时,就不会再释放堆内存了。所以也就避免了新对象属性指针i会变成悬空指针的问题。
一般情况传入移动构造函数中的那个右值,是将要生命周期结束的,或者说我们以后不会再使用到它了。但是还想要其对象里的内容(尤其是占大内存的对象)时。我们选择使用移动拷贝构造函数,效率高一些。
什么时候会触发移动构造函数呢?
Moveable m;
Moveable m2(std::move(m));//std::move(m)的唯一作用就是 将m强制转化为一个右值 。然后创建m2时调用的是移动构造函数。
注意:当类中没有定义移动构造函数时,这条语句Moveable m2(std::move(m));就会调用拷贝构造函数。
所以说是优先调用移动构造函数,没有的话,再调用拷贝构造函数。
std::move();//函数也是C++11中的新特性,作用就是把一个左值,转换成右值。

扩视机器视觉—Halcon机器视觉48个实战项目六(检测定位角度) 此项目halcon检测检测定位角度问题,并显示。 阅读详情

相关推荐

AI智能体协作:构建更精准的公司破产预测模型

公司破产预测对于金融机构、投资者和监管部门等具有至关重要的意义。准确的破产预测可以帮助金融机构提前做好风险防范,避免贷款损失;投资者可以根据预测结果调整投资组合,降低投资风险;监管部门可以及时发现潜在的金融风险,采取相应的监管措施。然而,传统的公司破产预测模型往往存在精度不高的问题,无法满足实际需求。本研究的目的是利用AI智能体协作的方式,构建一个更精准的公司破产预测模型。通过将多个AI智能体的优势进行整合,充分挖掘公司财务数据、市场数据等多源数据中的信息,提高预测的准确性和可靠性。

2501_92132293的博客 1081

C++中的移动构造函数和拷贝构造函数的区别

拷贝构造函数 拷贝构造函数用于从一个已存在的对象创建一个新的对象,即复制构造函数。它通常有一个类对象作为参数,返回一个新的对象,该对象与原始对象具有相同的值。如果一个类没有定义拷贝构造函数,则编译器会生成一个默认的拷贝构造函数,它将逐个复制所有非静态成员。如果一个类具有指针或引用成员,则需要自己编写拷贝构造函数,以确保正确地复制指针或引用所指向的对象。 移动构造函数和移动赋值运算符 移动构造函数...

Dijkstra_Liu 2034

SpringBoot与锐浪报表服务器深度整合实战指南

本文详细介绍了SpringBoot与锐浪报表服务器的深度整合实战指南,包括环境准备、Windows/Linux系统配置、核心功能实现代码解析及常见问题解决方案。通过具体案例和代码示例,帮助开发者高效完成报表系统的集成与部署,提升企业级应用的报表处理能力。

weixin_29238147的博客 369

C++构造、析构、拷贝构造、拷贝赋值、移动构造、移动赋值之二

一、概述 拷贝和移动是操作类对象的另外两种重要的方式。在类中的定义方式如下: class T{ public: T(const T&); //拷贝构造 T(T&&); //移动构造 T& operator=(const T&); //拷贝赋值 T& operator=(T&&); //移动赋值 } 在程序中发生,拷贝和移动在如下情况下默认发生

大隐隐于野 1168

《计算机网络》复试问答题总结

DNS 是一个联机分布式数据库系统,负责主机名和 IP 地址之间的转换,需要进行域名查询的机器主动发起域名解析请求,域名服务器则随时准备做出响应。域名服务器的数据库中存放着它所管辖范围的主机名和 IP 地址之间的映射表,域名服务器之间又可以相互联络和协作,以便分布在 Internet 各个域名服务器数据库中的域名都能被有效地搜索,从而实现主机名与 IP 地址的映射。为了提高解析效率,使用了域名缓存技术。在服务器、主机中设置一个专用的内存缓冲区。服务器用来存放近期解析过的域名及其对应的 IP 地址的映射。

weixin_45971154的博客 2027

手把手教你:基于STM32H7自制飞控,如何从零开始移植PX4固件(附避坑指南)

本文详细介绍了如何基于STM32H7自制飞控板并移植PX4固件的完整流程,包括硬件设计、开发环境搭建、关键配置文件移植、驱动开发与适配等关键步骤。特别针对PX4-AutoPilot的移植过程提供了实用技巧和避坑指南,帮助开发者高效完成飞控系统开发。

weixin_30271335的博客 143

【C++学习记录5】移动构造函数与拷贝构造函数对比

介绍了移动构造函数和拷贝构造函数的区别,以及右值引用的概念

weixin_44355021的博客 4215

Nuvoton OpenTitan开源安全芯片技术解析与应用

硬件安全模块(HSM)作为可信计算基的核心组件,其设计透明度和可验证性正成为行业焦点。RISC-V架构凭借开源特性,为构建可审计的安全芯片提供了新范式。OpenTitan项目通过开放Verilog源码和形式化证明,实现了从物理不可克隆函数(PUF)到分层安全启动的全栈透明。该方案在lowRISC Voyager开发板上实测显示,安全启动时间小于200ms,性能损耗仅7%,显著优于传统黑盒方案。目前该技术已应用于Chromebook和数据中心,其40nm工艺版本更将功耗降至5μA待机水平,为物联网和边缘计算提

weixin_36303807的博客 397

C++11移动构造函数详解

这里写目录标题拷贝构造函数修改后的拷贝构造函数移动构造函数移动构造函数的优点 当类中同时包含拷贝构造函数和移动构造函数时,如果使用临时对象初始化当前类的对象,编译器会优先调用移动构造函数来完成此操作。只有当类中没有合适的移动构造函数时,编译器才会退而求其次,调用拷贝构造函数。 拷贝构造函数 C++在三种情况下会调用拷贝构造函数(可能有纰漏),第一种情况是函数形实结合时,第二种情况是函数返回时,函数栈区的对象会复制一份到函数的返回去,第三种情况是用一个对象初始化另一个对象时也会调用拷贝构造函数。 除了这三种情

TABE_的博客 8748

HQChart实战教程49-点击修改K线颜色及背景色

HQChart实战教程49-点击修改K线颜色及背景色需求效果图步骤1. 注册点击监听事件2. 修改K颜色添加一个自定义颜色的K线klineoption清空所有自定义颜色的K线option交流QQ群: 950092318HQChart代码地址完整例子 需求 对点击的K线修改颜色。 效果图 步骤 1. 注册点击监听事件 事件ID JSCHART_EVENT_ID.ON_CLICK_CHART_PAINT, 注册监听事件见教程 HQChart使用教程5- K线图控件操作函数说明 this.Create=func

小银 2911

使用Matlab与V-REP联合仿真

在Matlab中,我们可以使用V-REP提供的远程API(Application Programming Interface)来连接到V-REP仿真环境。为了连接Matlab与V-REP,我们需要在Matlab中添加V-REP的远程API函数库。你可以根据具体的需求编写Matlab脚本来控制V-REP场景中的机器人,并进行系统建模和仿真。一旦成功连接到V-REP,我们可以使用Matlab来控制V-REP场景中的机器人。在本文中,我们将介绍如何使用Matlab与V-REP进行联合仿真,并提供相应的源代码。

HackMasterX的博客 1853

C++11新特性:移动构造函数和移动赋值

移动构造函数就是从拷贝构造函数演化而来的。 拷贝构造函数又分为浅拷贝和深拷贝: 浅拷贝:当类中有指针时,浅拷贝会发生错误 深拷贝:每次都是重新赋值一份,在某些情况下这种方法可能内存消耗较大 因此就产生了移动构造函数, 将原来对象的东西移动到新的对象上 移动后当对象销毁时不能发生错误 移动后原对象不再指向被移动的资源,这些资源的所有权已经归属新创建的对象 A(A&x){ this->num = new int(*x.num); cout &l...

双鱼座boyy的博客 7859

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

拷贝构造函数和移动构造函数的区别

拷贝构造函数和移动构造函数

amstlsx的博客 1700

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

C++ 移动构造函数与move()

移动构造函数的使用,move()使用实例。

那年聪聪 3310

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

【C++】左值、右值、移动拷贝构造函数、移动赋值函数

左值和右值的定义以及区别:

qq_45829112的博客 1022

拷贝构造和移动构造的区别是什么?

使用一个已有对象来复制初始化一个新对象。会将资源(如内存)复制一份,两个对象拥有各自独立的资源。使用一个右值(临时对象或将亡值)来**“移动”资源**,而不是复制。把资源的所有权从other转移给新对象,other被置为“空”或安全状态。极大提升性能,避免不必要的内存分配和复制。方面拷贝构造移动构造参数类型const T&T&&作用复制资源,两个独立对象转移资源,避免复制资源管理申请新资源,复制数据直接“偷走”资源指针,无需申请性能相对较慢,涉及深拷贝。

qq_44815135的博客 467

移动拷贝构造函数和移动赋值函数的写法

#include"pch.h" #include<iostream> using namespace std; class A { public: A(int _X, int *_P) :x(_X),p(new int(*_P)) { cout << "构造函数" << endl; }; A(const A &a) { if (this =...

铩羽 921

拷贝构造函数、拷贝赋值操作符、移动构造函数,移动赋值操作符

首先我们说一下什么是拷贝构造函数。拷贝构造函数(Copy Constructor)是c++中的一种特殊的构造函数,它用于创建一个对象并将其初始化为同一类中另一个对象的副本。拷贝构造函数通常以引用方式)接受一个同类对象作为参数,然后根据这个参数的值创建一个新的对象,使新对象与参数对象的内容相同。说的简单点就是用同一个类的实例构造一个新的实例。拷贝结束后被复制对象的资源依旧存在。

Roger_Spencer的博客 455

深入浅出移动构造函数与move之间的关系

首先看一个小例子: #include <iostream> #include <cstring> #include <cstdlib> #include <vector> using namespace std; int main() { string st = "I love xing"; vector<string> vc ; vc.push_back(move(st)); cout<<vc[0]

Clement 543

c++ 类与默认函数、包括构造函数和析构函数的特点

构造函数和析构函数不能被继承,但子类可以调用基类的构造函数和析构函数. 构造函数和析构函数是用来处理对象的创建和析构的,它们只知道对在它们的特殊层次的对象做什么。所以,在整个层次中的所有的构造函数和析构函数都必须被调用,也就是说,构造函数和析构函数不能被继承。 子类的构造函数会显示的调用父类的构造函数或隐式的调用父类的默认的构造函数进行父类部分的初始化。析构函数也一样。它们都是每个类都有的东西,如果能被继承,那就没有办法初始化了。 不是所有的函数都能自动地从基类继承到派生类中的。 在创建子类对象时,为

baidu_16370559的博客 871

C++ 封装(类和对象、构造函数的几种类型——拷贝、类型转换、移动构造函数)

一、封装 ——可以达到,对外提供接口,屏蔽数据,对内开放数据 C语言中的封装:当单一变量无法完成描述需求的时候,结构体类型解决了这一问题。 C++的封装:class封装的本质,在于将数据和行为,绑定在一起通过对象来完成操作。 二、类和对象 1、类的声明 2、权限修饰符:public、private(set/get)、protected 3、面向对象编程实例:栈的实现 4、析构函数 析构函数是类的一...

ytt999的博客 530

C++ 引用、构造函数、移动语义

1、引用 C++中的引用主要用作函数的形参,接近于const指针,必须在创建时初始化。 以Person类为例,如下: Person p; //调用P的构造函数,创建对象P Person &p2 = p; //引用变量P2指向P Person p3 = p2; //P2是引...

weixin_30363817的博客 148

【C++基础】类的构造函数和析构函数

构造函数是一个在对象创建时自动调用的函数,用于初始化对象的成员变量。构造函数的名称必须与类名相同,且没有返回类型(不包括void。

m0_63956046的博客 1391

移动语义和拷贝语义的区别

移动语义通常在以下情况下非常有用:当对象包含大量资源(如动态分配的内存、文件句柄等)时,进行拷贝操作可能会非常昂贵,而移动语义可以高效地将资源转移,避免不必要的复制。当一个对象被初始化或赋值给另一个对象时,如果存在移动构造函数和移动赋值运算符,并且右值可以被移动,编译器会优先调用移动构造函数和移动赋值运算符进行移动操作。例如:在 C++中,使用 std::vector 的移动构造函数可以快速地将一个 vector 对象的内容转移到另一个 vector 对象中,而不需要逐个复制元素。

qq_73652541的博客 523

C++笔记:拷贝函数和移动函数

拷贝构造函数: 在初始化一个类类型时,如果调用拷贝构造函数,就会把传入的参数先拷贝一份副本,再用此副本来进行初始化,格式一般是 class(const class&),一般在用 = 定义变量时使用,如 my_class s1 = s2;此时会调用拷贝构造函数,这里的参数得注意,一定得是引用类型的,假如是非引用的,则你调用拷贝构造函数时,我们需要拷贝它的实参,但为了拷贝实参,我们又需要调用拷贝构造

tomato。 3101

C++ 拷贝控制(一):拷贝构造函数

拷贝控制,当定义一个类时,我们显式或隐式地指定在此类型的对象拷贝、移动、赋值和销毁时做什么。通过一下五种特殊的成员函数来控制这些操作:拷贝构造函数、移动构造函数、拷贝赋值运算符、移动赋值运算符、析构函数。如果我们没有定义这些拷贝控制成员,编译器会自动定义确实操作。因此很多类,忽略了这些拷贝控制操作。但是,有些类依赖这些操作默认的定义会导致意想不到的灾难。.........

休息一下接着来的博客 270
上一篇: 聊一聊const和static限定符
下一篇: vcpkg下载及安装
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值