std::move_iterator仅适用于字符串类型?验证与问题分析
std::move_iterator的移动语义表现:并非仅针对字符串
经测试发现,很多开发者会误以为std::move_iterator仅对std::string这类类型生效,但本质原因是移动语义的行为取决于元素自身的类型:
- 对于拥有可转移资源的类型(如
std::string、std::vector等),移动操作会将资源从源对象转移到目标对象,源对象会进入有效但未定义的“空”状态; - 对于整数、bool这类平凡类型,移动操作和复制操作完全等价——因为它们没有需要转移的堆内存或外部资源,移动后源对象的值不会改变。
以下是验证示例:
示例1:std::move_iterator对std::string的移动效果
#include <iostream> // std::cout #include <iterator> // std::move_iterator #include <vector> // std::vector #include <string> // std::string #include <algorithm> // std::copy using namespace std; int main () { vector<string>src = {"one", "two", "three", "four"}, des(4); using Iter = vector<string>::iterator; // 使用move_iterator移动元素 move_iterator<Iter>beginitr(src.begin()); move_iterator<Iter>enditr(src.end()); Iter diter = des.begin(); while(beginitr != enditr) { *diter++ = *beginitr++; } cout << "src container size: " << src.size() << endl; cout << "data: " ; for_each(begin(src),end(src), [](string x){cout << x ;}); cout << endl << "THE END"; return 0; }
运行输出:
src container size: 4 data: THE END
这里源容器的std::string对象在被移动后,内部的字符缓冲区被转移到目标容器的对象中,因此源字符串变为空。注意容器的大小并未改变——std::move_iterator不会删除源容器的元素,只是移动元素的内部资源。
示例2:std::move_iterator对int类型的效果
#include <iostream> // std::cout #include <iterator> // std::move_iterator #include <list> // std::list #include <algorithm> // std::copy using namespace std; int main () { list<int>src = {1,2,3,4}, des(4); using Iter = list<int>::iterator; // 使用make_move_iterator创建移动迭代器 move_iterator<Iter>beginitr = make_move_iterator(src.begin()); move_iterator<Iter>enditr = make_move_iterator(src.end()); Iter diter = des.begin(); while(beginitr != enditr) { *diter++ = *beginitr++; } cout << "src container size: " << src.size() << endl; for_each(begin(src),end(src), [](int x){cout << x << endl;}); return 0; }
运行输出:
src container size: 4 1 2 3 4
对于整数这类平凡类型,移动操作的本质就是复制——因为它们没有可转移的资源,所以源对象的值不会发生变化。这并不是std::move_iterator失效,而是该类型的移动语义本身就与复制语义一致。
内容的提问来源于stack exchange,提问作者Hardik
相关产品推荐
相关产品推荐

