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

C++资源控制哲学:从push_back与emplace_back看左值右值

一、从问题开始std::vectorPerson people; Person bob(bob, 22); people.push_back(bob); // 左值 people.push_back(Person(alice, 25)); // 右值 people.emplace_back(charlie, 30); // 直接构造为什么需要这么多插入方式它们之间有什么区别二、值类别左值与右值的本质2.1 什么是左值什么是右值在C中每个表达式都有两个属性类型如int、Person、std::string值类别左值、右值等Person bob(bob, 22); // bob是左值有名称 Person(alice, 25); // 临时对象是右值无名称 42 // 字面量是右值2.2 如何判断左值/右值左值lvalue的判断标准有名称的变量bob、x、name可以取地址的bob字符串字面量hello特殊是左值返回左值引用的函数调用右值rvalue的判断标准临时对象Person(alice, 25)字面量除字符串外42、true算术表达式a bstd::move的结果Lambda表达式templatetypename T void check_value_category(T param) { if constexpr (std::is_lvalue_reference_vT) { std::cout 左值\n; } else { std::cout 右值\n; } } int main() { Person bob(bob, 22); check_value_category(bob); // 左值 check_value_category(std::move(bob)); // 右值 check_value_category(Person(alice, 25)); // 右值 check_value_category(42); // 右值 }2.3 左值/右值的本质资源所有权的表达class MyString { char* data; public: // 左值版本资源需要复制 MyString(const MyString other) { data new char[other.size]; memcpy(data, other.data, other.size); std::cout 深拷贝\n; } // 右值版本资源可以偷 MyString(MyString other) noexcept { data other.data; // 偷指针 other.data nullptr; // 置空源对象 std::cout 移动资源\n; } };核心理解左值我还在用这个资源你要用就得复制一份右值这个资源我不要了你直接拿去吧三、push_back与emplace_back的深度对比3.1 基本用法区别#include vector #include string #include iostream struct Person { std::string name; int age; Person(std::string n, int a) : name(n), age(a) { std::cout 构造函数被调用\n; } Person(const Person other) : name(other.name), age(other.age) { std::cout 拷贝构造函数被调用\n; } Person(Person other) noexcept : name(std::move(other.name)), age(other.age) { std::cout 移动构造函数被调用\n; } }; int main() { std::vectorPerson people; people.reserve(10); // push_back 左值拷贝 Person bob(bob, 22); people.push_back(bob); // 拷贝构造 // push_back 右值移动 people.push_back(Person(alice, 25)); // 构造临时 移动 // emplace_back 直接构造零拷贝 people.emplace_back(charlie, 30); // 直接构造 }输出构造函数被调用: bob 拷贝构造函数被调用: bob 构造函数被调用: alice 移动构造函数被调用: alice 构造函数被调用: charlie3.2 性能对比struct BigData { std::arrayint, 10000 data; std::string name; BigData(const char* n) : name(n) { std::cout 构造 name \n; } BigData(const BigData other) : name(other.name), data(other.data) { std::cout 拷贝 name (10000个int)\n; } BigData(BigData other) noexcept : name(std::move(other.name)), data(std::move(other.data)) { std::cout 移动 name \n; } }; // 性能测试 std::vectorBigData v; v.reserve(10); // 1. emplace_back: 一次构造 v.emplace_back(对象1); // 最佳性能 // 2. push_back 临时对象: 构造 移动 v.push_back(BigData(对象2)); // 尚可 // 3. push_back 左值: 拷贝昂贵 BigData obj3(对象3); v.push_back(obj3); // 深拷贝10000个int // 4. push_back 移动语义: 移动高效 v.push_back(std::move(obj3)); // 转移资源3.3 常见误区澄清std::vectorstd::string v; // 错误的写法 v.emplace_back(std::string(hi)); // 多此一举构造临时 移动 // 正确的写法 v.emplace_back(hi); // 最佳直接构造 v.push_back(hi); // 尚可构造临时 移动 v.push_back(std::string(hi)); // 尚可构造临时 移动 // 错误的理解 Person obj(obj, 1); v.push_back(obj); // 拷贝 v.emplace_back(obj); // 也是拷贝不是直接构造四、为什么需要这么多选择4.1 资源控制的演进// C98: 只有拷贝效率低下 people.push_back(bob); // 必须拷贝 // C11: 有了移动语义可以转移资源 people.push_back(std::move(temp)); // 移动资源而非拷贝 // C11: 直接构造零拷贝 people.emplace_back(bob, 22); // 直接在容器内存构造4.2 实际应用场景// 游戏开发中的纹理管理 class Texture { GLuint textureID; public: Texture(const char* path) { std::cout 加载纹理: path \n; glGenTextures(1, textureID); // 加载图像到GPU } // 禁止拷贝昂贵且不合理 Texture(const Texture) delete; // 允许移动转移GPU资源所有权 Texture(Texture other) noexcept : textureID(other.textureID) { other.textureID 0; } ~Texture() { if (textureID) { glDeleteTextures(1, textureID); } } }; std::vectorTexture textures; textures.emplace_back(player.png); // 加载一次直接存入 textures.emplace_back(enemy.png); // 另一个纹理 // textures.push_back(textures[0]); // 编译错误拷贝被禁止 textures.push_back(std::move(textures[0])); // 允许转移所有权4.3 完美转发极致的控制templatetypename T class Vector { private: T* data; size_t size; size_t capacity; public: // 左值版本拷贝 void push_back(const T value) { new (data size) T(value); // placement new size; } // 右值版本移动 void push_back(T value) { new (data size) T(std::move(value)); size; } // 完美转发直接构造 templatetypename... Args void emplace_back(Args... args) { new (data size) T(std::forwardArgs(args)...); size; } };五、最佳实践指南5.1 选择规则std::vectorPerson people; Person bob(bob, 22); // 场景1已有对象想要拷贝 people.push_back(bob); // 明确表示拷贝 // 场景2已有对象想要转移所有权 people.push_back(std::move(bob)); // 明确表示移动 // 场景3构造新对象 people.emplace_back(alice, 25); // 最佳性能 // 场景4临时对象 people.push_back(Person(charlie, 30)); // 可以触发移动 people.emplace_back(charlie, 30); // 更好直接构造5.2 性能总结操作构造次数拷贝/移动适用场景push_back(obj)01次拷贝需要保留原对象push_back(std::move(obj))01次移动放弃原对象所有权push_back(Temp())1次构造1次移动使用临时对象emplace_back(args...)1次构造0构造新对象5.3 常见陷阱// 陷阱1不必要的emplace_back std::string s hello; v.emplace_back(s); // 还是拷贝不如用 push_back(s) // 陷阱2误解emplace_back的行为 v.emplace_back(std::string(hi)); // 构造临时 移动多此一举 // 陷阱3忽略reserve std::vectorBigData v; v.emplace_back(data); // 可能触发多次拷贝扩容时 v.reserve(100); // 预分配内存避免扩容拷贝六、总结6.1 C资源控制的哲学零开销抽象你不需要为不需要的特性付出代价精确控制你可以选择最合适的方式来管理资源显式优于隐式重要的操作应该显式表达6.2 核心理解左值/右值是资源所有权的表达方式拷贝意味着资源复制移动意味着所有权转移emplace_back是最佳性能的选择但要注意使用场景push_back语义更清晰适合处理已有对象6.3 最终建议// 记住这个简单的选择标准 - 已有对象想要保留原对象push_back(obj) - 已有对象愿意转移所有权push_back(std::move(obj)) - 构造新对象emplace_back(args...) - 处理临时对象优先用 emplace_backC给你这么多选择不是为了增加复杂度而是为了让你能够在需要的时候进行精确的资源控制。理解这些概念你就能写出既高效又清晰的C代码。

相关文章:

C++资源控制哲学:从push_back与emplace_back看左值右值

一、从问题开始std::vector<Person> people; Person bob("bob", 22);people.push_back(bob); // 左值 people.push_back(Person("alice", 25)); // 右值 people.emplace_back("charlie", 30); // 直接构造为什么需要这么多插入…...

OpenClaw、Agent、Skill、MCP 深度解读与区分分析

引言&#xff1a;AI从"对话"到"行动"的范式转移在人工智能的发展历程中&#xff0c;我们正经历一场深刻的范式转移。传统的AI工具&#xff08;如早期ChatGPT&#xff09;主要扮演"建议者"角色&#xff0c;能生成文本、提供建议&#xff0c;但无法…...

WorkBuddy 实用培训课程内容体系:从入门到精通的“数字员工”养成指南

构建的 WorkBuddy&#xff08;基于OpenClaw架构&#xff09;实用培训课程内容体系。本体系深度解构了OpenClaw的技术原理、生态应用与安全实践&#xff0c;旨在培养具备专业能力的“数字员工”管理者与开发者。课程前言&#xff1a;AI 范式转移——从“建议者”到“执行者”在人…...

APM基础概念普及:应用性能管理的全面解析

在当今数字化时代&#xff0c;企业应用的性能直接影响着用户体验和商业成功。应用性能管理&#xff08;Application Performance Management&#xff0c;APM&#xff09;作为保障应用稳定运行的关键技术&#xff0c;已成为现代IT运维不可或缺的工具。本文将全面解析APM的基础概…...

夸克网盘自动化助手:彻底告别手动转存的智能管理方案

夸克网盘自动化助手&#xff1a;彻底告别手动转存的智能管理方案 【免费下载链接】quark_auto_save 夸克网盘签到、自动转存、命名整理、发推送提醒和刷新媒体库一条龙 项目地址: https://gitcode.com/gh_mirrors/qu/quark_auto_save 还在为每天重复的夸克网盘转存操作而…...

解锁Intel GPU的CUDA能力:从零开始的跨硬件计算实践

解锁Intel GPU的CUDA能力&#xff1a;从零开始的跨硬件计算实践 【免费下载链接】ZLUDA CUDA on non-NVIDIA GPUs 项目地址: https://gitcode.com/GitHub_Trending/zl/ZLUDA 当实验室电脑只有Intel集成显卡却需要运行CUDA加速程序时&#xff0c;当笔记本的Iris Xe显卡面…...

入门首选:8bit逐次逼近型SAR ADC电路设计成品,基于SMIC 0.18工艺,3.3V供...

8bit逐次逼近型SAR ADC电路设计成品 入门时期的第三款sarADC&#xff0c;适合新手学习等。 包括电路文件和详细设计文档。 smic0.18工艺&#xff0c;单端结构&#xff0c;3.3V供电。 整体采样率500k&#xff0c;可实现基本的模数转换&#xff0c;未做动态仿真&#xff0c;文档内…...

脉冲注入法与电感法无刷电机BLDC控制器方案

脉冲注入法&#xff0c;持续注入&#xff0c;启动低速运行过程中注入&#xff0c;电感法&#xff0c;ipd&#xff0c;力矩保持&#xff0c;无霍尔无感方案&#xff0c;媲美有霍尔效果。 bldc控制器方案&#xff0c;无刷电机。 提供源码&#xff0c;原理图。一、文档引言 本文基…...

基于注意力机制的多尺度卷积神经网络在滚动轴承故障诊断中的应用

基于注意力的多尺度卷积神经网络轴承故障诊断 针对传统方法在噪声环境下诊断精度低的问题&#xff0c;提出了一种多尺度卷积神经网络的滚动轴承故障诊断方法 首先&#xff0c;构建多尺度卷积提取不同尺度的故障特征&#xff0c;同时引入通道注意力自适应地选择包含故障特征的通…...

无人船编队 无人车编队 MPC 模型预测控制 多智能体协同控制 一致性 MATLAB 无人车 USV

无人船编队 无人车编队 MPC 模型预测控制 多智能体协同控制 一致性 MATLAB 无人车 USV 带原文献一、代码核心定位与应用场景 本套MATLAB源码针对自主水下航行器&#xff08;AUV&#xff09;、无人船&#xff08;USV&#xff09;、无人车等多智能体系统&#xff0c;实现了基于事…...

MDIN380芯片高清视频处理方案:SDI转VGA与LVDS转换,专业PCB设计与源码集成

MDIN380 SDI转VGA 转LVDS VGA转SDI 高清视频处理 MDIN380芯片 PCB代码方案资料 3G-SDI转VGA ?3G-SDI转LVDS ?高清视频 MDIN380、GV7601 芯片方案(PCB图和源码)。 此方案是韩国视频处理芯片MDIN380的整合应用方案。 3G-SDI转VGA或3G-SDI转LVDS。 方案共有两块电路板(一块底板…...

字符串题目

字符串输入char s[10];fgets(s,10,stdin);int lenstrlen(s);if(s[len-1]\n){s[len-1]0;}len--;拼数#include <stdio.h> #include <string.h>#define MAX 100005char res[MAX][20]; int n;int cmp(const void *a,const void *b) {char *pa(char*)a;char *pb(char*)b…...

如何快速掌握DownKyi:从新手到专家的完整视频下载指南

如何快速掌握DownKyi&#xff1a;从新手到专家的完整视频下载指南 【免费下载链接】downkyi 哔哩下载姬downkyi&#xff0c;哔哩哔哩网站视频下载工具&#xff0c;支持批量下载&#xff0c;支持8K、HDR、杜比视界&#xff0c;提供工具箱&#xff08;音视频提取、去水印等&#…...

RK3399 DRM显示框架实战:从零开始搭建多图层视频播放器

RK3399 DRM显示框架实战&#xff1a;从零构建多图层视频播放器 在智能终端设备开发领域&#xff0c;如何高效实现多媒体内容的叠加显示一直是工程师们面临的挑战。想象一下&#xff0c;当我们需要在教育平板上同时播放教学视频、展示动态课件和实时标注内容时&#xff0c;传统的…...

2025Reddit养号实战:3步打造高Karma账号矩阵

1. Reddit养号基础&#xff1a;为什么Karma值如此重要&#xff1f; 如果你刚接触Reddit&#xff0c;可能会对这个平台的"Karma系统"感到困惑。简单来说&#xff0c;Karma就像你在Reddit社区里的信用积分&#xff0c;它决定了你的发言权和影响力。我刚开始运营Reddit账…...

从频谱仪读数到测试报告:深入理解dBμV/m、dBm这些单位在EMC辐射发射测试中的真实含义

从频谱仪读数到测试报告&#xff1a;深入理解dBμV/m、dBm这些单位在EMC辐射发射测试中的真实含义 在电磁兼容&#xff08;EMC&#xff09;测试实验室里&#xff0c;工程师们每天都要面对频谱分析仪上跳动的数字——那些以dBμV/m、dBm为单位的读数&#xff0c;直接决定着产品能…...

P1113 杂务【洛谷算法习题】

P1113 杂务 网页链接 P1113 杂务 题目描述 John 的农场在给奶牛挤奶前有很多杂务要完成&#xff0c;每一项杂务都需要一定的时间来完成它。比如&#xff1a;他们要将奶牛集合起来&#xff0c;将他们赶进牛棚&#xff0c;为奶牛清洗乳房以及一些其它工作。尽早将所有杂务完…...

Kevin喜欢零(困难版本)【牛客tracker 每日一题】

Kevin喜欢零(困难版本) 时间限制&#xff1a;1秒 空间限制&#xff1a;256M 网页链接 牛客tracker 牛客tracker & 每日一题&#xff0c;完成每日打卡&#xff0c;即可获得牛币。获得相应数量的牛币&#xff0c;能在【牛币兑换中心】&#xff0c;换取相应奖品&#xff0…...

全开源同城论坛小程序:打造本地生活服务新入口

在本地生活服务赛道愈发火热的当下&#xff0c;一款功能完备、开源可定制的同城论坛小程序&#xff0c;无疑是开发者和创业者的得力工具。今天要给大家分享的这套全开源同城论坛小程序源码&#xff0c;不仅涵盖二手交易、房屋出租两大高频本地需求&#xff0c;还集成了LBS定位与…...

2026 最新全开源壁纸头像小程序源码:自带流量主,完美适配微信生态

在微信小程序生态中&#xff0c;壁纸、头像类工具凭借高频使用、低门槛运营的特性&#xff0c;一直是个人开发者与创业者试水流量变现的优质选择。2026 年最新推出的全开源壁纸头像小程序源码&#xff0c;不仅解决了传统开发的繁琐流程&#xff0c;更自带流量主功能、高清生成能…...

Poppins字体完整指南:免费获取专业级多语言排版解决方案

Poppins字体完整指南&#xff1a;免费获取专业级多语言排版解决方案 【免费下载链接】Poppins Poppins, a Devanagari Latin family for Google Fonts. 项目地址: https://gitcode.com/gh_mirrors/po/Poppins 你是否正在寻找一款既美观又支持多语言的免费字体来提升设计…...

旋转ReDet目标检测环境配置、旋转ReDet目标检测模型代跑训练、旋转ReDet目标检测模型改进创新旋转ReDet目标检测环境配置:Windows、Ubuntu、Centos、Macos等系统

旋转ReDet目标检测环境配置、 旋转ReDet目标检测模型代跑训练、 旋转ReDet目标检测模型改进创新 旋转ReDet目标检测环境配置&#xff1a;Windows、Ubuntu、Centos、Macos等系统环境&#xff0c;如果电脑拥有显卡&#xff0c;可配置GPU版本的ReDet环境。 旋转ReDet目标检测模型代…...

flac3d7.0主应力方向导出与可视化:使用fish导出单元体数据并用matlab绘制塑性区图

flac3d7.0主应力方向的导出并绘图 使用fish将单元体的三个主应力方向数据导出&#xff0c;并使用matlab绘图&#xff0c;可只对部分区域(如塑性区)的数据进行绘图在岩土工程数值模拟后处理中&#xff0c;三维主应力方向可视化是个挺有意思的活。今天咱们直接上手实操&#xff0…...

终极指南:用XUnity自动翻译器让外文游戏秒变中文

终极指南&#xff1a;用XUnity自动翻译器让外文游戏秒变中文 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator 还在为看不懂外文游戏而烦恼吗&#xff1f;XUnity自动翻译器是你的完美解决方案&#xff01;这…...

4步高效实现OneNote Markdown导出:从迁移到深度应用指南

4步高效实现OneNote Markdown导出&#xff1a;从迁移到深度应用指南 【免费下载链接】onenote-md-exporter ConsoleApp to export OneNote notebooks to Markdown formats 项目地址: https://gitcode.com/gh_mirrors/on/onenote-md-exporter 当你需要将多年积累的OneNot…...

orientation误差表示

目录1 Orientation误差&#xff08;最常见方法&#xff09;误差旋转Python实现2 Orientation RMSE3 位置 姿态一起计算&#xff08;SE(3)&#xff09;4 Python实现&#xff08;SE3误差&#xff09;5 机器人领域常见指标6 实践建议&#xff08;很重要&#xff09;总结orientati…...

SECS协议实战:从报警触发到Trace数据采集的完整指南

1. SECS协议基础与报警管理实战 半导体设备通信领域有个"隐形语言"叫SECS/GEM协议&#xff0c;它就像设备间的摩斯密码。今天咱们重点聊聊其中两个高频功能&#xff1a;报警管理&#xff08;S5F1&#xff09;和Trace数据采集&#xff08;S2F23/S6F1&#xff09;。先看…...

uniapp组件-Card卡片:从基础到高级应用全解析

1. 初识uni-app Card卡片组件 第一次接触uni-app的Card卡片组件时&#xff0c;我正为一个电商项目发愁。产品经理要求实现商品列表的卡片式布局&#xff0c;既要有图片展示&#xff0c;又要有价格和购买按钮。当时尝试自己写CSS实现&#xff0c;结果各种兼容性问题让我头疼不已…...

在华为OpenEuler上同时安装Python 3.8.6和3.9.0,我是如何解决依赖冲突和whl包不全问题的

在华为OpenEuler上实现Python 3.8.6与3.9.0双版本共存的实战指南 当开发环境需要同时支持Python 3.8.6和3.9.0时&#xff0c;许多开发者都会面临依赖冲突、whl包不兼容等问题。特别是在华为OpenEuler这样的企业级操作系统上&#xff0c;系统自带的Python版本可能无法满足特定项…...

别再乱配了!给COMSOL选工作站,CPU、内存、主板到底怎么搭才不浪费钱?

COMSOL工作站黄金配置法则&#xff1a;精准匹配需求&#xff0c;避开性能陷阱 当你面对琳琅满目的CPU型号、内存规格和主板参数时&#xff0c;是否感到无从下手&#xff1f;COMSOL Multiphysics作为一款强大的多物理场仿真工具&#xff0c;其性能表现与硬件配置息息相关。但盲目…...