点击上方【蓝字】关注博主
“ 移动迭代器是 C++11 中移动语义的扩展应用,它允许在 STL 中进行高效的元素移动操作,提高代码效率和性能。然而,在使用移动迭代器时需要注意数据丢失问题,并可以通过范围库等工具简化代码表达。”
背景
C++11 的引入带来了许多新的语言特性和标准库扩展,其中一些特性协同工作以提供更强大、更灵活的编程方式。移动迭代器便是 STL 与移动语义协作的产物,它们允许开发者在简洁的代码中表达一系列重要的概念。
C++ 中移动语义的先决条件
在理解移动迭代器之前,我们需要了解移动语义的概念。移动语义是一种 C++11 中引入的优化技术,它允许在不进行复制的情况下将资源所有权从一个对象转移到另一个对象。
2.1、传统的复制机制
在移动语义出现之前,C++ 中唯一的对象实例化方式是通过复制:
class MyType {
public:
MyType(const MyType& otherObject) // 复制构造函数
{
// 执行将 otherObject 复制到此对象的代码
}
...
};
请注意:源对象(otherObject参数)是const。这可以是看成必须的,因为要进行复制,源对象只是用作模型,不需要被修改。
复制操作虽然可靠,并且被广泛使用,但在某些情况下会导致效率低下。例如,当一个对象包含指向动态分配内存的指针时,复制操作需要分配新的内存并复制数据,这会增加时间和空间开销。在这种情况下,进行复制并不是最好的解决方案。而且,如果可以通过修改源对象来更快地传输数据,那么利用它将非常有用。
事实证明,修改源对象有时可以加快数据传输速度。以 std::string 为例。它通常会将字符存储在一个动态分配的数组中。对于正在构造的字符串,获取源字符串数组的所有权比在复制过程中分配自己的数组要快得多。
2.2、移动语义的引入
class MyType {
public:
MyType(MyType&& otherObject) // 移动构造函数
{
// 执行快速资源转移的代码,可能会修改 otherObject
}
...
};
2.3、使用 std::move
进行显式移动
std::string s;
std::string sByCopy = s; // 调用复制构造函数
std::string sByMove = std::move(s); // 调用移动构造函数
移动迭代器
移动迭代器是 STL 中的一项新功能,它允许在不进行复制的情况下将容器中的元素移动到另一个容器。
3.1、移动迭代器的用途
std::vector<std::string> source = { "Move", "iterators", "in", "C++" };
std::vector<std::string> destination(begin(source), end(source));
Source contains: "Move" "iterators" "in" "C++"
Destination contains: "Move" "iterators" "in" "C++"
Source contains: "" "" "" ""
Destination contains: "Move" "iterators" "in" "C++"
std::vector<std::string> destination = std::move(source);
Source contains:
Destination contains: "Move" "iterators" "in" "C++"
3.2、如何使用移动迭代器
std::vector<std::string> source = { "Move", "iterators", "in", "C++" };
std::vector<std::string> destination(std::make_move_iterator(begin(source)),
std::make_move_iterator(end(source)));
Source: "" "" "" ""
Destination: "Move" "iterators" "in" "C++"
3.3、移动迭代器的注意事项
使用移动迭代器时,需要注意以下几点:
移动迭代器会导致源容器中的元素失去其内容,因此在使用移动迭代器之后,应该避免再次使用源容器中的元素。
如果移动迭代器被错误地使用,例如将元素移动到一个需要复制操作的函数中,会导致数据丢失。
使表达一个简单事物所需的代码量激增。
避免数据丢失
std::vector<std::string> source = { "Move", "iterators", "in", "C++" };
std::vector<std::string> destination;
std::copy_if(std::make_move_iterator(begin(source)),
std::make_move_iterator(end(source)),
std::back_inserter(destination),
[](std::string word){ return word.length() == 4; }); // 丢失数据!
Source: "" "" "" ""
Destination: ""
std::vector<std::string> source = { "Move", "iterators", "in", "C++" };
std::vector<std::string> destination;
std::copy_if(std::make_move_iterator(begin(source)),
std::make_move_iterator(end(source)),
std::back_inserter(destination),
[](std::string const& word){ return word.length() == 4; });
Source: "" "iterators" "in" "C++"
Destination: "Move"
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <string>
int main() {
std::vector<std::string> source = { "Move", "iterators", "in", "C++" };
std::vector<std::string> destination;
// 使用移动迭代器将元素移动到 destination
std::copy(std::make_move_iterator(begin(source)),
std::make_move_iterator(end(source)),
std::back_inserter(destination));
// 打印结果
std::cout << "Source: ";
for (auto const& w : source) {
std::cout << '"' << w << '"' << ' ';
}
std::cout << "Destination: ";
for (auto const& w : destination) {
std::cout << '"' << w << '"' << ' ';
}
std::cout << std::endl;
return 0;
}
Source: "" "" "" ""
Destination: "Move" "iterators" "in" "C++"
范围库的简化
source | view::move; // 创建一个移动范围
总结
移动迭代器是 C++11 中移动语义的扩展应用,它允许在 STL 中进行高效的元素移动操作,提高代码效率和性能。然而,在使用移动迭代器时需要注意数据丢失问题,并可以通过范围库等工具简化代码表达。
公众号: Lion 莱恩呀
微信号: 关注获取
扫码关注 了解更多内容
点个 在看 你最好看