简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!
优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
1.前言
本篇目的:理解C++之使用与不使用std::move的区别。
2.std::move介绍
1.std::move作用
std::move
是 C++11 引入的一个函数模板,主要用于转移指针的所有权。
-
- 转移所有权:
std::move
将对象的所有权从一个对象转移到另一个对象,通过将参数转换为右值引用,实现对移动语义的支持。
- 转移所有权:
-
- 避免不必要的拷贝:在某些情况下,可以通过使用
std::move
来避免不必要的拷贝操作,减少资源消耗。
- 避免不必要的拷贝:在某些情况下,可以通过使用
-
- 支持移动语义:通过使用
std::move
,可以明确表示对于某个对象的移动操作,以提高性能和减少内存占用。
- 支持移动语义:通过使用
-
- 实现移动构造函数和移动赋值操作符:在自定义类中,可以通过使用
std::move
来实现移动构造函数和移动赋值操作符,实现高效的对象转移。
- 实现移动构造函数和移动赋值操作符:在自定义类中,可以通过使用
-
- 转移临时对象的所有权:在使用临时对象时,可以使用
std::move
来明确地将临时对象的所有权转移到另一个对象上。
- 转移临时对象的所有权:在使用临时对象时,可以使用
-
- 支持移动语义的标准库类型:许多标准库中的类型(如
std::string
、std::vector
等)都提供了移动构造函数和移动赋值运算符,可以通过std::move
来显式地调用这些函数。
- 支持移动语义的标准库类型:许多标准库中的类型(如
-
- 支持移动语义的模板编程:在模板编程中,使用
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}); // 将临时向量的所有权转移给 processVector
return 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