cpp 转发和移动

server/2024/10/21 10:09:17/

std::forward 和 std::move 在内存上的区别

1. std::move

std::move 是一个标准库函数模板,用于将其参数显式地转换为右值引用。这在需要将对象的资源移动而不是复制时非常有用,例如在移动构造函数或移动赋值操作中。

  • 语法:
template <class T>
typename std::remove_reference<T>::type&& move(T&& t) noexcept;
  • 使用示例:
#include <iostream>
#include <utility>
#include <vector>class MyClass {
public:std::vector<int> data;MyClass(std::vector<int> d) : data(std::move(d)) {std::cout << "Move constructor called" << std::endl;}
};int main() {std::vector<int> vec = {1, 2, 3, 4, 5};MyClass obj(std::move(vec));std::cout << "vec size after move: " << vec.size() << std::endl; // vec size is 0return 0;
}

在这个例子中,std::move(vec) 将 vec 转换为右值引用,因此 MyClass 的构造函数会移动 vec 的数据,而不是复制。

2. std::forward

std::forward 是一个条件性转发函数模板,根据传入的参数类型决定是返回左值引用还是右值引用。它通常用于泛型编程中保持参数的值类别。

  • 语法:
template <class T>
T&& forward(typename std::remove_reference<T>::type& arg) noexcept;
  • 使用示例:
#include <iostream>
#include <utility>void process(int& x) {std::cout << "Lvalue reference: " << x << std::endl;
}void process(int&& x) {std::cout << "Rvalue reference: " << x << std::endl;
}template <typename T>
void wrapper(T&& arg) {process(std::forward<T>(arg));
}int main() {int a = 5;wrapper(a);       // 调用 process(int&)wrapper(10);      // 调用 process(int&&)return 0;
}

在这个例子中,std::forward(arg) 根据 arg 的类型保持其值类别,从而正确地调用 process 的左值引用或右值引用版本。

3. 在内存上的区别
  • std::move:

  • 将左值转换为右值引用,意味着可以将资源从一个对象移动到另一个对象,而不是复制。

  • 目标对象将获取资源的所有权,源对象将被置于一种“有效但未指定”的状态(例如,容器的大小为0,但其内存仍然被分配)。

  • 内存管理: 主要用于避免不必要的拷贝,提高性能。

  • std::forward:

  • 保持传入参数的原始值类别,在泛型编程中尤为重要。

  • 如果传入参数是左值,std::forward 会返回左值引用;如果传入参数是右值,std::forward 会返回右值引用。

  • 内存管理: 确保参数在传递过程中保持其值类别,避免不必要的拷贝或移动。

4. 总结
  • std::move:

  • 用于明确地将对象转换为右值引用,以进行资源移动。

  • 改变了对象的状态(源对象被移动,资源转移到目标对象)。

  • std::forward:

  • 用于泛型编程中保持参数的原始值类别。

  • 在完美转发中非常重要,确保参数在传递过程中不改变其值类别。


http://www.ppmy.cn/server/95386.html

相关文章

Vue 3 完整应用开发与扩展教程

目录 Vue 3 完整应用开发与扩展教程前言1. 综合项目开发1.1 选定项目1.2 项目初始化1.3 结构设计1.4 组件开发1.4.1 ArticleList.vue1.4.2 ArticleItem.vue1.4.3 ArticleEditor.vue 1.5 路由配置1.6 状态管理1.7 表单处理 2. 服务端渲染&#xff08;SSR&#xff09;与 Nuxt.js2…

学习笔记——交通安全分析17

目录 前言 学习笔记整理 6城郊主干道交通安全分析 结束语 前言 #随着上一轮SPSS学习完成之后&#xff0c;本人又开始了新教材《交通安全分析》的学习 #整理过程不易&#xff0c;喜欢UP就点个免费的关注趴 #本期内容接上一期16笔记 学习笔记整理 6城郊主干道交通安全分析 …

在 Manim 中,line_func函数的介绍

在 Manim 中&#xff0c;line_func 参数可以使用多种线条类来绘制线条。以下是一些常用的线条类&#xff0c;您可以根据需要选择使用&#xff1a; Line: 最基本的线条类&#xff0c;用于绘制直线。 DashedLine: 绘制虚线的线条类。 Arrow: 带箭头的线条&#xff0c;非常适合表示…

Django中的超级管理员相关操作

超级管理员操作 场景描述添加超级管理员删除超级管理员更改超级管理员名称 场景描述 在进行管理员操作的时候&#xff0c;密码忘记&#xff0c;导致超级管理员无法使用&#xff0c;因此网上搜索相关操作&#xff0c;进行总结记录 相关操作都是在控制台完成 Terminal 添加超级管…

electron-builder打包vue2项目问题合集

一、打包之后不显示elecmentui的图标 1、使用版本 vue ^2.6.14element-ui ^2.15.14vue-cli-plugin-electron-builder 2.1.1 2、解决办法 1&#xff09; 如果是简单的图标可以使用图片代替&#xff08;这种对于elementui组件的图标还是不会显示&#xff09; 2&#xff09;在v…

XML 学习笔记

简介&#xff1a; &#xff08;1&#xff09;XML&#xff1a;可扩展性标记语言&#xff0c;用于传输和存储数据&#xff0c;而不是展示数据&#xff0c;是W3C 推举的数据传输格式。 XML的标签必须自定义&#xff0c;但是在写标签名的时候一定要有含义。 XML 只能有一个根节点…

什么是人工智能 (AI)

1955年9月&#xff0c;达特茅斯学院&#xff08;Dartmouth College&#xff09;年轻的数学助理教授约翰麦卡锡&#xff08;John McCarthy&#xff09;大胆提出&#xff0c;“原则上&#xff0c;学习的各个方面或智力的任何其他特征都可以被精确地描述&#xff0c;以至于可以制造…

嵌入式linux相机 图像处理模块

V4L2接口捕获图像数据&#xff0c;OpenCV简单图像处理 OpenCV提供了大量的图像处理功能&#xff0c;包括滤波、边缘检测、几何变换 #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <linux/videodev2.h> #include <sys/…