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

C++11之move移动语义

最近在学move语义,在网上搜索到的文章看不懂,左值引用、右值引用...搞的好乱,问了一下deepseek,举了几个例子,然后我好像懂了move的大致用法,当然右值引用还是不懂,本文章大概总结一下关于move的用法,当做笔记了hhh(根据deepseek的回答总结出来的),很浅,如果想深入理解move可以跳过。

通俗解释 move 语义

想象一下你有一本书,你现在想把它给你的朋友。

不用 move(拷贝): 你跑去复印店,把整本书复印一份,然后把复印本给你的朋友。你自己还留着原版书。这个过程(复印)既费钱(消耗内存)又费时间(消耗CPU周期)。

用 move(移动): 你直接走过去,把原版书递到你朋友手里。这本书的所有权就从你转移到了你朋友。你手上不再拥有这本书(但它处于一个“有效但空”的状态,比如你可以再买一本新的放回手里)。

移动语义的核心思想就是“所有权转移”,它避免了不必要的深层复制,极大地提升了性能,尤其是对于管理着大量资源的对象(如字符串、向量、文件句柄等)。

1、用于容器操作

最常见的场景,用于高效地将元素放入或移出容器。

#include <iostream>
#include <queue>
#include <functional>using namespace std;int main() {queue<function<void()>> q;// 向队列中添加一个任务q.push([]() { cout << "Hello from task!\n"; });cout<<"q.size()="<<q.size()<<endl;cout<<"q.front()的调用:";q.front()();   //调用队列中的第一个函数// 正确(高效)的方式:移出任务function<void()> task = move(q.front()); // 这里用 move!cout<<"task的调用:";task(); // 执行任务cout<<"-------------------------"<<endl;//此时队列大小仍为1,但是队首元素已不可用,因为被转移了cout<<"q.size()="<<q.size()<<endl;//如果强行使用,会抛出异常try{q.front()();}catch(const std::exception& e){std::cerr << e.what() << '\n';}return 0;
}

输出:

2、拷贝对象

#include <iostream>
#include <vector>
#include <functional>using namespace std;//使用move
void test01(){std::vector<int> v1 = {1, 2, 3};std::vector<int> v2 = std::move(v1);// 现在 v1 不再是 {1,2,3} 了,它很可能是一个空向量cout<<"v1:";for(int& i:v1){cout<<i<<' ';}cout<<endl;cout<<"v2:";for(int& i:v2){cout<<i<<' ';}cout<<endl;
}//不使用move
void test02(){std::vector<int> v1 = {1, 2, 3};std::vector<int> v2 = v1;// 现在 v1 仍是 {1,2,3} cout<<"v1:";for(int& i:v1){cout<<i<<' ';}cout<<endl;cout<<"v2:";for(int& i:v2){cout<<i<<' ';}cout<<endl;//将v2下标为1的元素修改为100v2[1]=100;cout<<"v1:";for(int& i:v1){cout<<i<<' ';}cout<<endl;cout<<"v2:";for(int& i:v2){cout<<i<<' ';}cout<<endl;
}int main(int argc, const char *argv[]){test01();cout<<"--------------"<<endl;test02();return 0;
}

输出:

3、实现高性能的swap

template<class T>
void swap(T& a, T& b) {T temp = std::move(a); // a 的资源移动给 tempa = std::move(b);      // b 的资源移动给 ab = std::move(temp);   // temp 的资源(原是a的)移动给 b
}
// 整个过程没有任何昂贵的拷贝,只有三次低成本的所有权转移。

4、构造函数的初始化列表中初始化类成员

#include<iostream>
using namespace std;
#include<functional>class MyClass {std::string m_name;
public:// 使用移动语义来初始化成员,避免拷贝MyClass(std::string name) : m_name(std::move(name)) {// 此时参数 name 已被移空,不能再使用它cout<<"name: "<<name<<endl;}void printInfo(){cout<<"m_name: "<<m_name<<endl;}
};int main(int argc, char const *argv[]){std::string s = "Hello";MyClass obj(s); // 构造 obj 时,s 被拷贝给参数 name,然后 name 被移动给 m_nameobj.printInfo();return 0;
}

输出:

http://www.dtcms.com/a/393167.html

相关文章:

  • 【计算机三级备考】真题总结
  • Linux基础指令(上)
  • Protocol Buffers .NET 运行时从核心 API 到工程实战
  • DFT教程 part1 VASP安装与学习推荐
  • 泛函 Φ(u) 驻点所满足的偏微分方程与自然边界条件
  • 基于springboot的健康饮食营养管理系统
  • C语言入门指南:联合体与枚举
  • JS逆向 -去哪儿滑块
  • C++包装器(Wrapper)概述
  • java后端工程师进修ing(研一版‖day47)
  • 小谈:物联网(IoT)与工业传感器技术
  • python标准库
  • 01 Tasking软件安装及新建工程
  • ​​[硬件电路-288]: 单路双输入异或门(门控开关:两个同时为1,输出为1)NC7SZ86L6X 功能概述与管脚定义
  • 声明式事务4
  • 速通ACM省铜第十天 赋源码(A Good Problem和Make It Beautiful和Gellyfish and Baby‘s Breath)
  • 寰宇光锥舟
  • 如何安全的计算softmax?
  • 第一部分:基础架构与入门
  • [Windows] Cencrack在线工具包6.52
  • 算法基础篇(2)模拟
  • Go基础:Go语言结构体(Struct)和接口(Interface)详解
  • 【计算机毕业设计】基于生成对抗网络的动作与表情一致性动漫角色生成算法系统​
  • html5 做个人网页识芯平夹回拼翘
  • 开收价均值策略
  • 【大模型部署】Ollama部署gguf模型
  • Coze源码分析-资源库-删除工作流-前端源码-核心组件
  • 机器学习实战第八章 降维
  • 2025年csp-j真题和解析
  • C++ STL map 深度解析:从原理到实战的全方位指南