百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

彻底理解且用对移动语义std:move()

ztj100 2025-01-21 23:13 15 浏览 0 评论

c++中移动语义std:move()定义:

template <class T>
typename remove_reference<T>::type&& move (T&& arg) noexcept {
    return static_cast<remove_reference<decltype(arg)>::type&&>(arg);
}
  1. 作用:将左值转为右值引用。
  2. 使用场景:将不再继续使用的左值继续用在其它方面,以节省内存开销和对象拷贝开销。
  3. 原理理解:

Many components of the standard library implement move semantics, allowing to transfer ownership of the assets and properties of an object directly without having to copy them when the argument is an rvalue.

翻译:许多标准库组件实现了移动语义,当对象是一个右值时,在不拷贝对象的情况下转移这个对象的资源和属性的拥有权。

理解:

(1) 这个对象必须是一个右值;

(2) 不用拷贝对象;

(3) 是转移的对象资源的拥有权,如图1。


Although note that -in the standard library- moving implies that the moved-from object is left in a valid but unspecified state. Which means that, after such an operation, the value of the moved-from object should only be destroyed or assigned a new value; accessing it otherwise yields an unspecified value.

翻译:尽管如此,在标准库里,移动语义说明被移动的对象处于有效但未指定的状态。也就是说,在std::move()执行后,被移动的对象的值应当被销毁或者赋予一个新值;访问这个被移动的对象会出现一个不确定的值。

理解:

(1) 对象经过std::move()执行后,处于有效但未指定的状态。

"有效但未指定"的理解:

如:Student stu2 = std::move(stu1); stu1是一个有效的声明,但是stu1里的值是不确定的。

4.实现原理。

如下代码,实现原理是:

(1)类中声明移动构造函数;

(2)std::move()将左值转为右值再调用时,就会调用移动构造函数;

(3)移动构造函数实现了两个功能点:a.数据初始化,2.销毁被移动对象数据。

class Info {
public:
  Info():age(0){}
  Info(int age):age(age){}
  int age;
};

class Student {
public:
  Student() : info(nullptr) {}
  Student(const Student& stu) { //拷贝构造函数
    cout << "constructor" << endl;
  }
  Student(Student&& stu) noexcept : info(stu.info) { //移动构造函数
    stu.info = nullptr;
    cout << "Move constructor" << endl;
  }
  ~Student() {};
  Info* info;
};

int main(){
  Student stu;
  stu.info = new Info(20);
  Student stu1(stu);  //调用拷贝构造函数
  cout << stu.info->age << endl;
  Student stu2(std::move(stu)); //调用移动构造函数
  cout << stu2.info->age << endl;
  return 0;
}
输出:
constructor
20
Move constructor
20


5.误用

(1)任何场景都用std::move(),但是其实是需要类中实现了移动语义功能才行(移动构造函数+数据初始化+销毁被移动对象数据)

int a = 100;
int b = std::move(a); //这样是不对的,这样依然进行了拷贝。

6.思考

需要透彻理解std::move(),还是需要根据其定义、原理,且结合实践代码理解,不实践写代码去实现移动语义是很难透彻理解的。

相关推荐

Java 8 新特性全面解读:解锁现代编程的魅力

Java8新特性全面解读:解锁现代编程的魅力Java8作为Java语言发展史上里程碑式的版本,不仅带来了诸多新特性,更深刻地改变了我们编写代码的方式。无论是简洁的Lambda表达式,还是强大的S...

教程:克隆公司饭卡 然后优雅地“蹭饭”

最近借了Proxmark3来娱乐性的玩下RFID技术,工资甚低的我只好拿公司饭卡实验,优雅地蹭几顿。物业大叔表打我啊!以下操作纯属学习目的,初学难免错误较多,望斧正。首先了解M1卡的结构:请参考htt...

新课标高中教材1030个短语大汇总(高中新课标英语词汇)

1.anamountof+不可数名词许多...

看完这篇文章你就懂 AQS 了(赛科龙aqs401参数详情)

前言谈到并发,我们不得不说AQS(AbstractQueuedSynchronizer),所谓的AQS即是抽象的队列式的同步器,内部定义了很多锁相关的方法,我们熟知的ReentrantLock、Ree...

Java 8新特性全面解析:开启现代化编程之旅

Java8新特性全面解析:开启现代化编程之旅Java8作为Java语言发展历程中的重要里程碑,在2014年正式发布。它的到来标志着Java从传统面向对象编程向支持函数式编程迈进的重要一步。在这一版...

Java 8新特性全面剖析:让代码更优雅、更高效

Java8新特性全面剖析:让代码更优雅、更高效Java8,作为Java语言发展史上的一座里程碑,带来了众多令人振奋的新特性。这些新特性不仅极大地提升了开发效率,还让代码变得更优雅、更简洁。今天,我...

线程安全编程方法总结(线程安全编程方法总结)

保护线程安全是多线程编程中的核心问题,关键在于控制共享资源的访问并协调线程间的执行顺序。以下是常用的基本方法及其适用场景:1.互斥锁(MutexLocks)机制:通过锁(如synchronize...

考勤数据标准化处理(考勤标准化管理制度)

经常做考勤的同学有没有遇到过这样的考勤数据呢?没错,从考勤机里导出来的,要统计那叫一个麻烦啊(有同学说可以导出txt文件,然后再处理会省事很多,有条件的小伙伴可以自己研究研究)看这表格数据其实挺规范的...

SQL语句大全,所有的SQL都在这里(sql语句百度百科)

一、基础1、说明:创建数据库CREATEDATABASEdatabase-name2、说明:删除数据库dropdatabasedbname3、说明:备份sqlserver---创建备份数...

手搓Agno智能体使用Ollama模型(ollama本地智能体)

轻量化智能体开源框架Agno有兴趣了解WhatisAgno-Agno安装python3.12...

高级排序算法之快速排序(高效排序)

前言今天继续算法学习,本次学习的是高级排序之快速排序。本文代码部分存在调用公共方法,可在文章:...

Linux cmp 命令使用详解(linux常用命令cp)

简介Linux中的...

N张图告诉你K-DB为什么能全面兼容Oracle?

不是每一款数据库都能全面兼容Oracle,就像不是所有数据库都可以被称之为K-DB。一般数据库能做到的SQL标准和函数上兼容Oracle,而K-DB则能实现更多,在数据库体系架构、集群方式、数据库对象...

12. Langchain评估与调试:用LangSmith优化模型表现

引言:从"感觉不错"到"数据说话"2025年某电商平台通过LangSmith系统化的评估优化,将客服机器人的问题解决率从68%提升至92%。本文将详解如何用...

那些有用但不为大家所熟知的 Java 特性

本文最初发表于PiotrMińkowski的个人站点Medium网站,经作者授权,由InfoQ中文站翻译分享。...

取消回复欢迎 发表评论: