惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
V2EX
博客园 - 叶小钗
Last Week in AI
Last Week in AI
Google DeepMind News
Google DeepMind News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Security Blog
Microsoft Security Blog
腾讯CDC
P
Proofpoint News Feed
大猫的无限游戏
大猫的无限游戏
The Cloudflare Blog
aimingoo的专栏
aimingoo的专栏
月光博客
月光博客
量子位
A
About on SuperTechFans
Engineering at Meta
Engineering at Meta
Apple Machine Learning Research
Apple Machine Learning Research
Jina AI
Jina AI
博客园 - Franky
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
人人都是产品经理
人人都是产品经理
D
DataBreaches.Net
博客园_首页
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Stack Overflow Blog
Stack Overflow Blog

博客园 - keleman

lambda 如何捕获 所在子线程ID 配置 git 到达 通过 git &&ssh 登录 gitee.com 和 github.com 整理于豆包问答,测试可以实现 由QThread::currentThread()引出的 如何在线程中安全运行任务 由豆包整理的 持有 std::unique_ptr 的 lambda → 不能放进 std::function 从豆包整理 C++ Lambda 捕获方式・安全写法速查表 整理自豆包 C++14 Lambda 相比 C++11 的核心改进 firefox 149 在 linux mint 21 上的 mozillia 源安装 qt GUI 如何利用q thread 和qfuturwatcher 实现 不阻塞主线程? xargs 和管道 |的区别 一加5t的volte怎么设置 做上位机软件设计 下位机软件设计 qt 将槽函数在子线程中执行的方法 以二级指针作为函数参数,并从函数中分配空间的原理 VS2017 设置 类模板参数推导(CTAD, Class Template Argument Deduction) postEvent 和 sendEvent的区别 QObject Event( )customEvent( ) 函数区别 关于实际项目中必要的几个文件操作接口 QwaitCondition.的工作原理 【Debian】更换软件 源出现的Certificate问题解决方法 linux PS1 提示符的颜色设置 python 的几个常用的函数 知识点 设置 docker 国内的 映像加速器 docker 容器安装软件 docke 容器设置代理 docker 安装问题
std::forward<T> ,std::move 使用场景的区别
keleman · 2025-02-28 · via 博客园 - keleman

std::move 的使用场景

std::move 主要用于将一个左值强制转换为右值引用,从而可以触发移动语义。它通常在以下场景中使用:

1. 转移资源所有权

当你想要将一个对象的资源(如动态分配的内存、文件句柄等)转移到另一个对象时,可以使用 std::move。例如,在使用标准库容器时,移动操作可以避免不必要的深拷贝,提高性能。
#include
#include

int main() {
std::vector vec1 = {1, 2, 3};
std::vector vec2 = std::move(vec1); // 转移 vec1 的资源到 vec2
std::cout << "vec1 size: " << vec1.size() << std::endl; // 输出 0
std::cout << "vec2 size: " << vec2.size() << std::endl; // 输出 3
return 0;
}

2. 自定义类的移动构造和移动赋值

在自定义类中,如果你想要实现移动构造函数和移动赋值运算符,需要使用 std::move 来将参数转换为右值引用,以便调用移动语义。
#include
#include

class MyClass {
public:
std::string data;

\ // 移动构造函数
MyClass(MyClass&& other) noexcept : data(std::move(other.data)) {
other.data.clear();
}

\ // 移动赋值运算符
MyClass& operator=(MyClass&& other) noexcept {
if (this != &other) {
data = std::move(other.data);
other.data.clear();
}
return *this;
}
};

int main() {
MyClass obj1;
obj1.data = "Hello";
MyClass obj2 = std::move(obj1); // 调用移动构造函数
std::cout << "obj1 data: " << obj1.data << std::endl; // 输出空字符串
std::cout << "obj2 data: " << obj2.data << std::endl; // 输出 "Hello"
return 0;
}

std::forward 的使用场景

std::forward 主要用于实现完美转发,即在模板函数中,将参数以原始的左值或右值属性转发给其他函数。它通常在以下场景中使用:

1. 函数模板的完美转发

当你编写一个函数模板,需要将参数原封不动地转发给另一个函数时,可以使用 std::forward。这样可以保证参数的左值或右值属性在转发过程中不被改变。
#include
#include

void print(int& value) {
std::cout << "Lvalue: " << value << std::endl;
}

void print(int&& value) {
std::cout << "Rvalue: " << value << std::endl;
}

template
void forwarder(T&& arg) {
print(std::forward(arg)); // 完美转发参数
}

int main() {
int x = 42;
forwarder(x); // 传递左值
forwarder(123); // 传递右值
return 0;
}

在上述代码中,forwarder 是一个函数模板,它接受一个通用引用 T&&。通过 std::forward(arg),可以将参数 arg 以原始的左值或右值属性转发给 print 函数。

2. 构造函数的完美转发

在类的构造函数中,如果你需要将参数完美转发给基类的构造函数或成员对象的构造函数,可以使用 std::forward。
#include
#include

class Base {
public:
Base(int value) {
std::cout << "Base constructor: " << value << std::endl;
}
};

class Derived : public Base {
public:
template<typename... Args>
Derived(Args&&... args) : Base(std::forward(args)...) {
std::cout << "Derived constructor" << std::endl;
}
};

int main() {
Derived d(42);
return 0;
}
在上述代码中,Derived 类的构造函数使用了可变参数模板和完美转发,将参数完美转发给 Base 类的构造函数。
综上所述,std::move 主要用于触发移动语义,转移资源所有权;而 std::forward 主要用于实现完美转发,保持参数的左值或右值属性。