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

std::move

std::move是 C++11 引入的移动语义核心工具

1.功能

std::move不移动任何东西,它是一个类型转换工具,将左值(有名字的变量)无条件转换为右值引用(T&&,从而“骗过”编译器,去调用移动构造函数或移动赋值运算符。

  • 目的:转移资源所有权(如堆内存、文件句柄),避免深拷贝的开销。

  • 效果:被移动的对象进入“有效但未指定”的状态(通常是空),不应再访问其内容(除非重新赋值)。


2. 基础用法

2.1 移动构造函数(转移堆内存)

class Buffer { int* ptr; public: // 移动构造函数(noexcept 是关键优化提示) Buffer(Buffer&& other) noexcept : ptr(other.ptr) { other.ptr = nullptr; // 防止析构时 double free } }; Buffer a; Buffer b = std::move(a); // 触发移动,a 变为空指针

noexcept是 C++11 引入的异常规范修饰符,核心作用:标记函数不抛异常编译器优化提示

2.2移动赋值运算符(转移并清理旧资源)

Buffer& operator=(Buffer&& other) noexcept { if (this != &other) { delete ptr; // 释放自己的旧资源 ptr = other.ptr; // 接管别人资源 other.ptr = nullptr; } return *this; } b = std::move(a); // 触发移动赋值

2.3 STL 容器的高效操作(最实用)

std::vector<std::string> v1 = {"a", "b"}; std::vector<std::string> v2 = std::move(v1); // O(1) 转移指针,不拷贝元素 // 向容器插入大对象,避免拷贝 std::vector<MyClass> vec; MyClass obj; vec.push_back(std::move(obj)); // 直接转移,不复制

3. 注意事项

  • 1:std::move若要用原变量,必须重新赋值后才安全。移动后访问是未定义行为(通常崩溃)。

    std::string s = "hello"; std::string t = std::move(s); std::cout << s; // 未定义行为!s 可能为空或乱码 s = "new"; // 重新赋值后可安全使用
  • 2:只有定义了移动构造函数的类型才高效移动(如std::vector)。简单类型(int)拷贝和移动无区别。

  • 3:const对象用std::move
    const std::vector<int> v;

  • 即使std::move(v),因为无法修改,会退化为拷贝(const 右值无法绑定到非 const 移动构造)。


4. 与std::forward的区别

工具作用使用场景
std::move无条件转为右值明确要转移资源时
std::forward有条件转为右值(保留原始类型)模板完美转发(转发参数给下一层函数)
template<typename T> void wrapper(T&& arg) { // 保持 arg 的原始左右值属性 other_func(std::forward<T>(arg)); }

5.T&&

T&&在 C++ 中根据上下文有两种完全不同的含义,分别是右值引用万能引用(转发引用)

判断标准:T是否被推导


5.1. 右值引用(Rvalue Reference)

T具体类型时,T&&就是右值引用。

  • 作用:绑定到即将销毁的临时对象,用于实现“移动语义”,窃取资源。

  • 特征:只能接收右值(临时量、std::move的结果)。

void func(std::vector<int>&& vec) { // T 是具体类型 vector<int> // 只能接收右值 } std::vector<int> v; func(std::move(v)); // 可以 func(v); // 编译报错,左值无法绑定到右值引用

5.2. 万能引用(Forwarding Reference)

T模板参数(且T由实参推导)时,T&&是万能引用。

  • 作用:在模板中保持值类别不变(左值保持左值,右值保持右值),常用于std::forward完美转发。

  • 特征:既能接收左值,也能接收右值。

template<typename T> void func(T&& arg) { // T 由实参推导,这里是万能引用 // 传左值 -> T 推导为 int& // 传右值 -> T 推导为 int } int x = 10; func(x); // 左值可以 func(20); // 右值也可以
  • func(x)x是左值intT推导为int&arg类型是int&(左值引用)

  • func(T&& arg) → func(int& && arg) (引用折叠)→ func(int& arg)

  • func(20)20是右值intT推导为intarg类型是int&&(右值引用)

  • func(T&& arg) → func(int&& arg)

引用折叠规则

原始类型折叠后
T& &T&
T& &&T&
T&& &T&
T&& &&T&&

5.3. 特殊情况:auto&&

auto&&也是万能引用,同样根据初始化表达式推导:

auto&& r1 = 10; // 右值 -> int&& int x = 5; auto&& r2 = x; // 左值 -> int&

4. const T&&

注意:const T&&永远是右值引用,不是万能引用,且极少使用(因为移动时通常不需要 const)。

http://www.jsqmd.com/news/1394380/

相关文章:

  • 业务与 AI 解耦:Java+Python 跨语言调用的 4 种企业级集成方案
  • CSI 内容结构指数:让内容创作可量化
  • 从I2S时钟域设计看AU-60与A-59F的采样率工程取舍
  • 北京酒店住宿行业GEO服务商怎么选?2026年代理加盟本地靠谱推荐 - 子柔传媒
  • 广州食品检测服务行业如何借助GEO抢占AI搜索入口?2026年本地靠谱服务商与代理加盟推荐 - 企业新闻快传
  • 广州新型材料企业如何抓住GEO代理加盟机遇?2026年本地靠谱服务商推荐指南 - 小随科技
  • 杭州广拓时代领跑 GEO 优化赛道,以空间智能抢占 AI 搜索流量核心高地 评估篇
  • LangChain Agent动态工具管理:Function Calling与自动注册实战
  • 沙盒环境下退款无REVOKE_REFUND_TRANSACTION通知
  • Win11 安装 WSL2 + Ubuntu 22.04 完整手册(国内网络 / 迁移 D 盘)
  • 3分钟学会抖音视频批量下载:douyin-downloader 完整上手指南
  • 【电商核心业务实战】(8) 使用RocketMQ优化订单超时取消流程
  • 防御性编程实战:从0.5行数据崩溃案例解析数据完整性保障
  • 0.005mm 高精度 CNC 加工:机器人薄壁复杂零件变形控制与全维度品控方案
  • 2026年电源连接器实力厂家甄选:工业配套的可靠之选 - 卓企推荐
  • 5分钟极速入门ChromaDB:从文本向量化到语义搜索实战
  • SWE-Bench ProMax:多语言代码重构基准测试的范式升级与工程实践
  • Inference-Time Distillation: Cost-Efficient Agents Without Fine-Tuning or Manual Prompt Engineering
  • AI画科研插图本身合规,为啥还有论文因此被撤稿?
  • 广州升学规划服务行业如何找到靠谱的GEO服务商?2026年本地代理加盟推荐指南 - 子柔传媒
  • 北京人力资源服务行业GEO服务商怎么选?代理加盟本地靠谱推荐指南 - 小随科技
  • 北京工商注册服务行业如何选择GEO服务商?2026年代理加盟本地靠谱推荐 - 小随科技
  • 2026年WhatsApp多账号的分群模型与差异化运营策略
  • LangChain -访问模型,创建智能体访问模型
  • RAG+Agent主程序架构设计:从核心原理到生产级实现
  • Ubuntu 20.04.6 LTS下使用docker运行android-battery-historian方法
  • 2026上海本土靠谱装修公司推荐:老房翻新、别墅装修、局部装修各有优势 - 优企甄选
  • DeepSeek-V4 Flash:大模型高效推理的技术突破与应用前景
  • ANSYS 2025 R1 本地安装与破解激活完整指南
  • 深入解析Claude Code Skills:元工具架构与AI编程助手核心机制