C++之使用std::move与否的实例区别(二百五十五)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

1.前言

本篇目的:理解C++之使用与不使用std::move的区别。

2.std::move介绍

1.std::move作用

std::move 是 C++11 引入的一个函数模板,主要用于转移指针的所有权。

    1. 转移所有权:std::move 将对象的所有权从一个对象转移到另一个对象,通过将参数转换为右值引用,实现对移动语义的支持。
    1. 避免不必要的拷贝:在某些情况下,可以通过使用std::move来避免不必要的拷贝操作,减少资源消耗。
    1. 支持移动语义:通过使用std::move,可以明确表示对于某个对象的移动操作,以提高性能和减少内存占用。
    1. 实现移动构造函数和移动赋值操作符:在自定义类中,可以通过使用std::move来实现移动构造函数和移动赋值操作符,实现高效的对象转移。
    1. 转移临时对象的所有权:在使用临时对象时,可以使用std::move来明确地将临时对象的所有权转移到另一个对象上。
    1. 支持移动语义的标准库类型:许多标准库中的类型(如std::stringstd::vector等)都提供了移动构造函数和移动赋值运算符,可以通过std::move来显式地调用这些函数。
    1. 支持移动语义的模板编程:在模板编程中,使用std::move可以明确表示对于对象的移动语义,使得代码更加清晰和高效。

std::move在 C++ 中扮演着非常重要的角色,为支持移动语义和提高性能提供了强大的工具。通过合理地利用std::move,可以实现对于对象所有权的有效转移,从而提高代码的性能和效率。

3.代码实例

1. 转移对象的所有权:std::move 可以将对象的所有权从一个对象转移到另一个对象,通过将参数转换为右值引用,实现对移动语义的支持。

#include <iostream>
#include <string>int main() {std::string source = "Hello, world!";std::string destination = std::move(source);std::cout << "source: " << source << std::endl;        // 输出:source: std::cout << "destination: " << destination << std::endl;  // 输出:destination: Hello, world!return 0;
}

2. 避免不必要的拷贝:在某些情况下,可以通过使用 std::move 来避免不必要的拷贝操作,减少资源消耗。

#include <string>void processString(std::string&& s) {// 处理字符串
}int main() {std::string str = "Hello";processString(std::move(str));  // 避免不必要的拷贝return 0;
}

3. 支持移动语义:通过使用 std::move,可以明确表示对于某个对象的移动操作,以提高性能和减少内存占用。

#include <vector>int main() {std::vector<int> source = {1, 2, 3};std::vector<int> destination = std::move(source);// 现在 source 为空,destination 包含原始数据return 0;
}

4. 实现移动构造函数和移动赋值操作符:在自定义类中,可以通过使用 std::move 来实现移动构造函数和移动赋值操作符,实现高效的对象转移。

#include <iostream>class MyObject {
public:// 移动构造函数MyObject(MyObject&& other) noexcept {// 执行资源移动}// 移动赋值操作符MyObject& operator=(MyObject&& other) noexcept {if (this != &other) {// 执行资源移动}return *this;}
};int main() {MyObject obj1;MyObject obj2 = std::move(obj1);  // 移动构造函数MyObject obj3;obj3 = std::move(obj2);           // 移动赋值操作符return 0;
}

5. 转移临时对象的所有权:在使用临时对象时,可以使用 std::move 来明确地将临时对象的所有权转移到另一个对象上。

#include <vector>void processVector(std::vector<int>&& vec) {// 处理移动过来的临时向量
}int main() {processVector(std::vector<int>{1, 2, 3}); // 将临时向量的所有权转移给 processVectorreturn 0;
}

6. 支持移动语义的标准库类型:许多标准库中的类型(如 std::string、std::vector 等)都提供了移动构造函数和移动赋值运算符,可以通过 std::move 来显式地调用这些函数。

#include <vector>int main() {std::vector<int> source = {1, 2, 3};std::vector<int> destination = std::move(source); // 调用 std::vector 的移动构造函数return 0;
}

7. 支持移动语义的模板编程:在模板编程中,使用 std::move 可以明确表示对于对象的移动语义,使得代码更加清晰和高效。

#include <utility>
#include <vector>template <typename T>
void processVector(T&& vec){std::vector<int> destination = std::move(vec);  // 显式调用 std::move,实现移动语义// 对 destination 进行处理
}int main() {std::vector<int> source = {1, 2, 3};processVector(std::move(source)); // 在模板函数中使用 std::move 实现移动语义return 0;
}

8.使用拷贝对象方式,打印两个vector对比

#include <iostream>
#include <vector>
#include <string>int main() {std::vector<std::string> v1{"hello", "world"};std::vector<std::string> v2;// 将v1的内容拷贝到v2中,此时两个对象都有值为:"hello world"的字符串v2 = v1;// v2现在包含了v1的元素std::cout << "v2 size: " << v2.size() << std::endl;for (const auto& s : v2) { // 遍历v2中的元素std::cout << s << " ";std::cout << std::endl;}printf("xxx--------------->%s, %s(), line = %d\n",__FILE__,__FUNCTION__,__LINE__);for (const auto& s : v1) { // 遍历v1中的元素std::cout << s << " ";std::cout << std::endl;}printf("xxx--------------->%s, %s(), line = %d\n",__FILE__,__FUNCTION__,__LINE__);return 0;
}

打印:
v1 size: 2
v2 size: 2
hello
world
xxx--------------->move_01.cpp, main(), line = 23
hello
world
xxx--------------->move_01.cpp, main(), line = 28

9.使用std::move转移对象方式,打印两个vector对比

#include <iostream>
#include <vector>
#include <string>int main() {std::vector<std::string> v1{"hello", "world"};std::vector<std::string> v2;// 将v1的内容移动到v2中,此时v1中的vecrot字符为空v2 = std::move(v1);// v1现在为空std::cout << "v1 size: " << v1.size() << std::endl;// v2现在包含了v1的元素std::cout << "v2 size: " << v2.size() << std::endl;for (const auto& s : v2) { // 遍历v2中的元素std::cout << s << " ";std::cout << std::endl;}printf("xxx--------------->%s, %s(), line = %d\n",__FILE__,__FUNCTION__,__LINE__);for (const auto& s : v1) { // 遍历v1中的元素std::cout << s << " ";std::cout << std::endl;}printf("xxx--------------->%s, %s(), line = %d\n",__FILE__,__FUNCTION__,__LINE__);return 0;
}

打印:
v1 size: 0
v2 size: 2
hello
world
xxx--------------->move_01.cpp, main(), line = 23
xxx--------------->move_01.cpp, main(), line = 28

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/177713.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计讯物联LoRa终端TW820多重优势共蓄能,强力驱动行业发展

LoRa&#xff0c;即远距离无线电&#xff0c;是一种低功耗宽区域网络(LPWAN)的通信技术。它在同样的功耗条件下比其他无线方式传播的距离更远&#xff0c;且比传统的无线射频通信距离扩大3-5倍&#xff0c;真正实现了低功耗、远距离、广覆盖的统一。基于LoRa通信技术的优势特点…

盘点49个Python网站项目Python爱好者不容错过

盘点49个Python网站项目Python爱好者不容错过 学习知识费力气&#xff0c;收集整理更不易。 知识付费甚欢喜&#xff0c;为咱码农谋福利。 链接&#xff1a;https://pan.baidu.com/s/1aFYJtNZjgst1l5KFBckP2A?pwd8888 提取码&#xff1a;8888 项目名称 A simpleshorturl…

现代浴室:从硬朗到柔美

现代浴室不再是冰冷的地方&#xff0c;而是一个温馨的角落。它是我们日常生活中的庇护所&#xff0c;一个能够唤起宁静和舒适感的地方。如今&#xff0c;浴室的设计注重的是颜色、材质、光线和表面的精心搭配&#xff0c;以创造一个柔和、温馨的空间。 与过去的硬朗陶瓷、锋利…

服务器监控及其监控工具

随着互联网技术的不断发展&#xff0c;服务器成为现代企业中不可或缺的一环。对于很多企业来说&#xff0c;服务器故障会给公司的日常工作和财务带来不小的影响。这时&#xff0c;服务器监控成为了保障服务器高效安全运行的一项重要工作。有许多监控工具可以帮助我们更好地监控…

二、服务拆分及远程调用

目录 一、注意事项&#xff1a; 1.单一职责: 2.数据独立: 3.面向服务&#xff1a; 二、服务拆分例子&#xff1a; 三、远程调用例子&#xff1a; 微服务调用方式&#xff1a; 四、提供者与消费者 服务调用关系&#xff1a; 一、注意事项&#xff1a; 1.单一职责: 不同…

go语言学习之旅之安装sdk环境,hello world!

学无止境 为什么学习Go语言 高效编程&#xff1a; Go语言被设计为一门高效的编程语言。其编译速度快&#xff0c;执行速度也相对较快&#xff0c;适合用于构建高性能的应用程序。 并发支持&#xff1a; Go语言天生支持并发编程&#xff0c;通过goroutine和channel提供了简单而…

Android---MVP 中 presenter 声明周期的管理

我们经常在 Android MVP 架构中的 Presenter 层做一些耗时操作&#xff0c;比如请求网络数据&#xff0c;然后根据请求后的结果刷新 View。但是&#xff0c;如果按返回结束 Activity&#xff0c;而 Presenter 依然在执行耗时操作。那么就有可能造成内存泄漏&#xff0c;严重时甚…

2023.11.14使用bootstrap制作一个简洁的前端注册登录页

2023.11.14使用bootstrap制作一个简洁的前端注册登录页 比较简洁的登录页&#xff0c;主要是为自己开发的一些平台页面做测试用&#xff0c;前端具备功能如下&#xff1a; &#xff08;1&#xff09;输入用户名、密码&#xff0c;需补充后端验证代码。 &#xff08;2&#xff…

Xshell远程登录 Linux小键盘数字输入变成字母解决办法

Xshell的设置问题&#xff0c;依次查看&#xff1a;文件-->属性-->终端-->VT模式-->初始数字键盘模式更改为&#xff1a;设置普通&#xff08;s&#xff09;

jQuery Ajax前后端数据交互

ajax是用来做前后端交互的&#xff0c;前端使用ajax去去发送一个请求&#xff0c;后端给其响应拿到数据&#xff0c;前端做些展示。 浏览器访问网站一个页面时&#xff0c; Web 服务器处理完后会以消息体方式返回浏览器&#xff0c;浏览器自动解析 HTML 内容。如果局部有新数…

如何选择工业以太网交换机?

现在市面上有许多品牌的工业以太网交换机&#xff0c;并且类型也相当复杂。在选择交换机的时候&#xff0c;需要考虑多个因素&#xff0c;比如工作环境、是否需要冗余配置、是否需要网管功能、是否需要非网管功能、以及未来的维护和扩展性等。通常情况下&#xff0c;当选择工业…