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

c++ 移动赋值/移动构造函数

在 C11 引入移动语义Move Semantics之前对象之间的赋值或初始化通常涉及深拷贝Deep Copy即复制所有数据。这对于包含动态分配资源如std::vector,std::string, 原始指针管理的内存的对象来说开销很大。移动构造函数和移动赋值运算符允许我们将资源的“所有权”从一个对象转移到另一个对象而不是复制数据。这极大地提高了性能特别是对于临时对象右值。1. 核心概念左值 vs 右值理解移动语义的前提是区分左值lvalue和右值rvalue左值有名字、有持久地址的对象如int a 10;中的a。右值通常是临时对象、字面量或即将销毁的对象如a b的结果或者函数返回的非引用对象。移动语义的核心思想是既然右值临时对象马上就要销毁了我们没必要复制它的资源直接“偷”过来用就行了。2. 移动构造函数 (Move Constructor)定义当一个新对象被一个右值初始化时调用。签名ClassName(ClassName other)参数接受一个右值引用T。作用将源对象other的资源指针直接转移给新对象并将源对象的指针置为nullptr或其他安全状态防止析构时重复释放内存。代码示例class MyVector { private: int* data; size_t size; public: // 构造函数 MyVector(size_t s) : size(s) { data new int[s]; std::cout 构造: 分配内存\n; } // 拷贝构造函数 (深拷贝) MyVector(const MyVector other) : size(other.size) { data new int[size]; std::copy(other.data, other.data size, data); std::cout 拷贝构造: 深拷贝内存\n; } // --- 移动构造函数 --- MyVector(MyVector other) noexcept : data(other.data), size(other.size) { // 关键步骤窃取指针 other.data nullptr; // 将源对象置为空防止其析构时释放这块内存 other.size 0; std::cout 移动构造: 转移所有权\n; } // 析构函数 ~MyVector() { if (data) { delete[] data; std::cout 析构: 释放内存\n; } } }; // 使用场景 MyVector createVector() { MyVector temp(100); return temp; // 返回临时对象右值 } int main() { // 这里会触发移动构造函数而不是拷贝构造 MyVector v createVector(); return 0; }3. 移动赋值运算符 (Move Assignment Operator)定义当一个已存在的对象被赋予一个右值时调用。签名ClassName operator(ClassName other)返回值通常返回*this以支持链式赋值。作用自赋值检查防止a std::move(a)导致错误。清理旧资源释放当前对象持有的旧资源。窃取新资源接管源对象的资源。重置源对象将源对象置于有效但未指定的状态通常指针置空。代码示例class MyVector { // ... (同上) ... public: // --- 移动赋值运算符 --- MyVector operator(MyVector other) noexcept { if (this ! other) { // 1. 自赋值检查 // 2. 释放当前资源 delete[] data; // 3. 窃取资源 data other.data; size other.size; // 4. 重置源对象 other.data nullptr; other.size 0; } std::cout 移动赋值: 转移所有权\n; return *this; } }; int main() { MyVector v1(10); MyVector v2(20); // std::move 将左值 v1 强制转换为右值引用触发移动赋值 v2 std::move(v1); // 此时 v1 内部指针为 nullv2 拥有了原本 v1 的内存 return 0; }4. 关键细节与最佳实践A.noexcept的重要性移动构造函数和移动赋值运算符必须标记为noexcept除非你真的可能抛出异常。原因标准库容器如std::vector在扩容重新分配内存时如果元素的移动操作是noexcept的它会优先使用移动否则为了保证异常安全如果移动中途失败原数据还在它只能退回到拷贝。如果不加noexceptstd::vectorMyVector的性能可能会退化回拷贝语义。B.std::move是什么std::move不移动任何东西。它只是一个强制类型转换工具将左值转换为右值引用T从而告诉编译器“这个对象我可以被移动请调用移动版本的操作”。调用std::move(x)后x处于有效但未指定的状态。除了销毁或重新赋值外不应再使用x的值。C. 规则之五 (Rule of Five)如果你需要自定义以下五个函数中的任何一个通常意味着你需要自定义全部五个析构函数拷贝构造函数拷贝赋值运算符移动构造函数移动赋值运算符如果你只定义了移动操作而没有定义拷贝操作编译器会自动删除默认的拷贝构造和拷贝赋值函数因为资源已经被移走了默认拷贝是不安全的。D. 成员变量的自动移动如果你的类成员变量本身支持移动语义如std::unique_ptr,std::vector,std::string你可以使用default让编译器自动生成高效的移动操作class MyClass { std::vectorint vec; std::string name; // 编译器自动生成的移动构造/赋值会分别调用 vec 和 name 的移动操作 // 非常高效且安全 MyClass(MyClass) default; MyClass operator(MyClass) default; };总结对比特性拷贝构造/赋值移动构造/赋值参数类型const T(左值引用)T(右值引用)行为深度复制数据 (Deep Copy)转移资源所有权 (Steal Pointers)源对象状态保持不变变为有效但未指定状态 (通常为空)性能较慢 (涉及内存分配和复制)极快 (仅指针赋值)适用场景需要保留源对象数据时源对象是临时值或不再需要时

相关文章:

c++ 移动赋值/移动构造函数

在 C11 引入移动语义(Move Semantics)之前,对象之间的赋值或初始化通常涉及深拷贝(Deep Copy),即复制所有数据。这对于包含动态分配资源(如 std::vector, std::string, 原始指针管理的内存&…...

HUNYUAN-MT 7B翻译终端轻量部署方案:在低显存GPU上的优化与调参

HUNYUAN-MT 7B翻译终端轻量部署方案:在低显存GPU上的优化与调参 你是不是也遇到过这种情况?看到一个大语言模型翻译效果不错,兴冲冲地想部署到自己的服务器上试试,结果一看显存要求——动辄几十个G,瞬间就劝退了。手头…...

Nanbeige 4.1-3B部署教程:阿里云ECS+Docker一键部署全流程

Nanbeige 4.1-3B部署教程:阿里云ECSDocker一键部署全流程 1. 环境准备与快速部署 1.1 阿里云ECS选购建议 在开始部署前,我们需要准备一台合适的云服务器。以下是推荐的阿里云ECS配置: 实例规格:ecs.g7ne.large(2核…...

Pixel Dimension FissionerGPU算力优化教程:显存占用降低40%实测步骤

Pixel Dimension Fissioner GPU算力优化教程:显存占用降低40%实测步骤 1. 工具介绍与优化目标 Pixel Dimension Fissioner是一款基于MT5-Zero-Shot-Augment核心引擎构建的文本改写工具,其独特的16-bit像素冒险工坊界面为用户带来沉浸式体验。然而&…...

探索嵌入式系统与物联网:ESP32环境监测网络的构建与实践

探索嵌入式系统与物联网:ESP32环境监测网络的构建与实践 【免费下载链接】arduino-esp32 Arduino core for the ESP32 项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32 在物联网技术飞速发展的今天,嵌入式系统如何实现高效的环境…...

HUNYUAN-MT Python爬虫数据清洗利器:自动化翻译非结构化文本

HUNYUAN-MT Python爬虫数据清洗利器:自动化翻译非结构化文本 你是不是也遇到过这种情况?辛辛苦苦写了个爬虫,从国外电商网站抓下来一堆商品信息,结果发现描述是英文的,评论是德语的,规格表又是日文的。数据…...

零基础入门前端JavaScript 基础语法详解(可用于备赛蓝桥杯Web应用开发)

一、注释注释是代码中不被执行的部分,用于说明代码功能。单行注释:// 这是单行注释多行注释:/* 这是多行注释 */二、变量声明JavaScript 中有三种变量声明方式,区别如下:关键字作用域变量提升重复声明重新赋值var函数作…...

AVR单片机EEPROM结构化存储库:类型安全+CRC校验

1. 项目概述 AcksenIntEEPROM 是一款专为 8-bit AVR 微控制器(如 ATmega328P、ATmega2560、ATtiny85 等)设计的 Arduino 兼容 EEPROM 数据持久化库。其核心定位并非替代底层 EEPROM.h ,而是提供 类型安全、顺序布局、带校验机制的高级抽象…...

别再空谈AIoT了!用ESP32和TensorFlow Lite Micro,手把手教你做个能识别人脸的智能门铃

从零构建AIoT智能门铃:ESP32-CAM与TensorFlow Lite Micro实战指南 当智能家居设备开始具备"思考"能力,技术魔法就悄然走进了日常生活。想象一下:门铃不仅能响铃,还能认出访客身份,自动向你的手机推送个性化提…...

嵌入式系统集成DeepSeek-OCR-2:资源受限环境优化

嵌入式系统集成DeepSeek-OCR-2:资源受限环境优化 1. 为什么嵌入式场景需要特别对待DeepSeek-OCR-2 在工业现场、智能终端和边缘设备上部署OCR能力,和在数据中心跑模型完全是两回事。我第一次把DeepSeek-OCR-2直接扔进一台ARM Cortex-A53的工控机时&…...

入门前端CSS 媒体查询全解析:从入门到精通,打造完美响应式布局(可用于备赛蓝桥杯Web应用开发)

一、什么是 CSS 媒体查询CSS 媒体查询是 CSS3 引入的核心特性,是对 CSS2 媒体类型的扩展。它的核心能力是先判断当前设备 / 环境的特性,当条件完全匹配时,再执行括号内的 CSS 样式规则。最典型的应用场景,就是根据屏幕宽度调整页面…...

国风美学生成模型v1.0硬件指南:STM32在交互装置中触发模型生成的联动设计

国风美学生成模型v1.0硬件指南:STM32在交互装置中触发模型生成的联动设计 你有没有想过,用毛笔在砚台上轻轻一磨,就能“磨”出一幅由AI创作的国风山水画?或者,在实体竹简上刻下几笔,就能触发AI生成一首古风…...

多模态扩展:OpenClaw整合Qwen3-32B实现截图内容分析

多模态扩展:OpenClaw整合Qwen3-32B实现截图内容分析 1. 为什么需要截图内容分析 在日常工作中,我们经常遇到需要从截图或界面中提取信息并执行后续操作的场景。比如收到一张包含客户联系方式的截图,需要手动输入到CRM系统;或是从…...

GLM-4-9B-Chat-1M长文本处理实战:基于Python的百万字符上下文分析

GLM-4-9B-Chat-1M长文本处理实战:基于Python的百万字符上下文分析 1. 引言 想象一下,你需要分析一本完整的《红楼梦》(约73万字),或者处理一份长达500页的法律合同,传统的大语言模型往往会因为上下文长度…...

OpenClaw模型微调:GLM-4.7-Flash适配专属自动化场景

OpenClaw模型微调:GLM-4.7-Flash适配专属自动化场景 1. 为什么需要专属模型微调 去年夏天,我花了整整三天时间调教家里的扫地机器人——不是因为它坏了,而是想让它学会识别我乱扔的袜子。这个经历让我明白:通用AI就像标准版扫地…...

如何验证BGE-Reranker-v2-m3是否正常工作?测试脚本教程

如何验证BGE-Reranker-v2-m3是否正常工作?测试脚本教程 当你部署好一个AI模型后,最关心的问题往往是:它真的能正常工作吗?今天我们就来解决这个问题。BGE-Reranker-v2-m3作为RAG系统中的关键组件,它的准确性直接影响到…...

手把手教你用LTspice仿真Buck变换器(含波形分析与参数优化)

手把手教你用LTspice仿真Buck变换器(含波形分析与参数优化) 在电力电子领域,Buck变换器作为最经典的降压型DC-DC拓扑,其仿真验证是每个工程师的必修课。LTspice作为一款免费且功能强大的电路仿真工具,能够帮助我们直观…...

Python实战:3种高效方法将TXT转CSV(附完整代码)

Python实战:3种高效方法将TXT转CSV(附完整代码) 在日常数据处理工作中,我们经常需要将文本文件(TXT)转换为更结构化的CSV格式。无论是处理日志文件、数据采集结果还是简单的数据交换,这种转换都…...

MedGemma X-Ray入门指南:中文医学术语理解能力测评(肺炎/肺不张/胸腔积液)

MedGemma X-Ray入门指南:中文医学术语理解能力测评(肺炎/肺不张/胸腔积液) 1. 引言:当AI遇见X光片 想象一下,你手头有一张胸部X光片,需要快速判断是否存在肺炎、肺不张或者胸腔积液。对于非放射科医生来说…...

PP-DocLayoutV3效果对比:传统OCR与智能文档分析的差距

PP-DocLayoutV3效果对比:传统OCR与智能文档分析的差距 你是不是也遇到过这种情况?用传统的OCR工具扫描一份合同或者报告,出来的文字顺序乱七八糟,表格变成了几行看不懂的代码,图片旁边的说明文字也不知道跑哪去了。最…...

嵌入式按钮去抖与多击识别库debounceButton

1. 项目概述debounceButton是一个轻量级、可移植的嵌入式按钮去抖与多击(double-click / triple-click)识别库,专为资源受限的 MCU(如 STM32F0/F1/F4、ESP32、nRF52、RP2040 等)设计。其核心目标并非仅实现硬件电平消抖…...

GTE中文嵌入模型应用场景解析:智能客服FAQ匹配、合同比对、专利查重

GTE中文嵌入模型应用场景解析:智能客服FAQ匹配、合同比对、专利查重 1. 什么是GTE中文文本嵌入模型 你可能已经用过各种AI工具,但有没有想过:当系统说“这两句话意思很接近”,它到底怎么判断的?答案就藏在文本嵌入&a…...

形态学算子实战指南:腐蚀、膨胀、开闭运算在工业检测中的精准应用

1. 工业检测中的形态学基础:从理论到实战 第一次接触形态学算子是在五年前的PCB板缺陷检测项目上。当时产线上有批电路板总是出现微小的短路和断路问题,传统阈值分割怎么调参数都搞不定。直到老工程师扔给我一行HALCON代码:opening_circle(Re…...

Java毕业设计基于SpringBoot架构的酒店后台管理系统

前言 Java基于B/S架构的酒店后台管理系统是一种功能全面、易于维护、跨平台的信息化解决方案。它可以帮助酒店实现高效、便捷的后台管理,提升酒店的运营效率和客户满意度。同时,该系统还具有良好的可扩展性和安全性,可以满足酒店不断变化的业…...

C# ABP vNext 模块化架构实战:从零构建一个可复用的业务模块

1. 从零开始理解ABP vNext模块化架构 第一次接触ABP vNext框架时,我被它强大的模块化能力深深吸引。记得当时接手一个电商系统重构项目,需要同时开发用户管理、商品管理和订单管理三大功能。传统开发方式下,这些功能都挤在一个项目里&#xf…...

Java毕业设计基于SpringBoot+Java Web的生鲜团购销售系统

前言 该系统适用于社区生鲜团购、农产品电商等场景。通过为社区居民提供便捷的生鲜团购服务,满足他们的日常购物需求。同时,通过优化供应链管理和营销策略,降低运营成本和提高销售额。 综上所述,SpringBoot基于JavaWeb的生鲜团购销…...

嵌入式莫尔斯电码编解码库:轻量纯C实现

1. Morse 编码/解码库技术解析:嵌入式系统中的轻量级字符-莫尔斯电码双向转换实现1.1 库定位与工程价值Morse 库是一个专为资源受限嵌入式环境设计的纯 C 语言轻量级编解码组件,其核心功能是实现 ASCII 字符串与莫尔斯电码二进制表示之间的确定性双向映射…...

5步掌握SWE-bench:评估语言模型编程能力的实战指南

5步掌握SWE-bench:评估语言模型编程能力的实战指南 【免费下载链接】SWE-bench SWE-Bench: Can Language Models Resolve Real-world Github Issues? 项目地址: https://gitcode.com/GitHub_Trending/sw/SWE-bench SWE-bench是当前评估语言模型在真实软件工…...

YOLOv5训练数据集报错?一招教你批量转换JPEG到JPG格式(附完整代码)

YOLOv5训练数据集格式兼容性问题全解析:从JPEG到JPG的高效批量转换方案 在计算机视觉项目的实际开发中,数据集准备往往是耗时最长且最容易出错的环节之一。最近在技术社区中,关于YOLOv5训练过程中遇到的ignoring corrupt image/label报错讨论…...

DeepSeek-OCR-2保姆级教程:Docker Compose编排OCR+PostgreSQL元数据服务

DeepSeek-OCR-2保姆级教程:Docker Compose编排OCRPostgreSQL元数据服务 1. 教程概述 1.1 学习目标 通过本教程,你将学会如何使用Docker Compose一键部署DeepSeek-OCR-2完整服务,包括OCR识别引擎、vLLM推理加速、Gradio前端界面以及Postgre…...