移动构造函数_C++ STL move_iterator移动迭代器用法详解

C++ 11 还为 STL 标准库增添了一种迭代器适配器,即本节要讲的 move_iterator 移动迭代器适配器。

move_iterator 迭代器适配器,又可简称为移动迭代器,其可以实现以移动而非复制的方式,将某个区域空间中的元素移动至另一个指定的空间。

#include #include #include #include using namespace std;int main(){    //创建并初始化一个 vector 容器    vector myvec{ "STL","Python","Java" };    //再次创建一个 vector 容器,利用 myvec 为其初始化    vectorothvec(myvec.begin(), myvec.end());      cout << "myvec:" << endl;    //输出 myvec 容器中的元素    for (auto ch : myvec) {        cout << ch << " ";    }    cout << endl << "othvec:" << endl;    //输出 othvec 容器中的元素    for (auto ch : othvec) {        cout << ch << " ";    }    return 0;}

程序执行结果为:

myvec:STL Python Javaothvec:STL Python Java

注意程序第 11 行,初始化 othvec 容器是通过复制 myvec 容器中的元素实现的。也就是说,othvec 容器从 myvec 容器中复制了一份 "STL"、"Python"、"Java" 并存储起来,此过程不会影响 myvec 容器。

那么,如果不想采用复制的方式,而就是想 myvec 容器中存储的元素全部移动到 othvec 容器中,该怎么办呢?没错,就是采用移动迭代器。

值得一提的是,实现移动迭代器的模板类定义在 头文件,并位于 std 命名空间中。因此,在使用该类型迭代器时,程序中应包含如下代码:

#include using namespace std;

实现 move_iterator 移动迭代器的模板类定义如下:

template class move_iterator;

可以看到,在使用此迭代器时,需要传入一个基础迭代器 Iterator。

注意,此基础迭代器的类型虽然没有明确要求,但该模板类中某些成员方法的底层实现,需要此基础迭代器为双向迭代器或者随机访问迭代器。也就是说,如果指定的 Iterator 类型仅仅是输入迭代器,则某些成员方法将无法使用。

C++ STL move_iterator的创建

move_iterator 模板类中,提供了 4 种创建 move_iterator 迭代器的方法。

1) 通过调用该模板类的默认构造函数,可以创建一个不指向任何对象的移动迭代器。比如:

//将 vector 容器的随机访问迭代器作为新建移动迭代器底层使用的基础迭代器typedef std::vector<:string>::iterator Iter;
//调用默认构造函数,创建移动迭代器std::move_iteratormIter;

由此,我们就创建好了一个 mIter 移动迭代器,该迭代器底层使用的是 vector 容器的随机访问迭代器,但这里没有为此基础迭代器明确指向,所以 mIter 迭代器也不知向任何对象。

2) 当然,在创建 move_iterator 迭代器的同时,也可以为其初始化。比如:

//创建一个 vector 容器std::vector<:string> myvec{ "one","two","three" };//将 vector 容器的随机访问迭代器作为新建移动迭代器底层使用的基础迭代器typedef std::vector<:string>::iterator Iter;//创建并初始化移动迭代器std::move_iteratormIter(myvec.begin());

这里,我们创建了一个 mIter 移动迭代器,同时还为底层使用的随机访问迭代器做了初始化,即令其指向 myvec 容器的第一个元素。

3) move_iterator 模板类还支持用已有的移动迭代器初始化新建的同类型迭代器,比如,在上面创建好 mIter 迭代器的基础上,还可以向如下这样为新建的移动迭代器初始化:

std::move_iteratormIter2(mIter);//还可以使用 = 运算符,它们是等价的//std::move_iteratormIter2 = mIter;

这样创建的 mIter2 迭代器和 mIter 迭代器完全一样。也就是说,mIter2 底层会复制 mIter 迭代器底层使用的基础迭代器。

4) 以上 3 种创建 move_iterator 迭代器的方式,其本质都是直接调用 move_iterator 模板类中的构造方法实现的。除此之外,C++ STL 标准库还提供了一个 make_move_iterator() 函数,通过调用此函数可以快速创建一个 move_iterator 迭代器。

C++ STL 标准库中,make_move_iterator() 是以函数模板的形式提供的,其语法格式如下:template move_iterator make_move_iterator (const Iterator& it);

其中,参数 it 为基础迭代器,用于初始化新建迭代器。同时,该函数会返回一个创建好的移动迭代器。

举个例子:

typedef std::vector<:string>::iterator Iter;std::vector<:string> myvec{ "one","two","three" };//将 make_move_iterator() 的返回值赋值给同类型的 mIter 迭代器std::move_iteratormIter = make_move_iterator(myvec.begin());#include #include #include #include using namespace std;int main(){    //创建并初始化一个 vector 容器    vector myvec{ "STL","Python","Java" };    //再次创建一个 vector 容器,利用 myvec 为其初始化    vectorothvec(make_move_iterator(myvec.begin()), make_move_iterator(myvec.end()));       cout << "myvec:" << endl;    //输出 myvec 容器中的元素    for (auto ch : myvec) {        cout << ch << " ";    }    cout << endl << "othvec:" << endl;    //输出 othvec 容器中的元素    for (auto ch : othvec) {        cout << ch << " ";    }    return 0;}

程序执行结果为:

myvec:othvec:STL Python Java

通过和程序一做对比不难看出它们的区别,由于程序第 11 行为 othvec 容器初始化时,使用的是移动迭代器,其会将 myvec 容器中的元素直接移动到 othvec 容器中。

注意,即便通过移动迭代器将容器中某区域的元素移动到了其他容器中,该区域内仍可能残留有之前存储的元素,但这些元素是不能再被使用的,否则极有可能使程序产生各种其他错误。

和其他迭代器适配器一样,move_iterator 模板类中也提供有 base() 成员方法,通过该方法,我们可以获取到当前移动迭代器底层所使用的基础迭代器。

举个例子:

#include #include #include #include using namespace std;int main(){    typedef std::vector<:string>::iterator Iter;    //创建并初始化一个 vector 容器    vector<:string> myvec{ "STL","Java","Python" };    //创建 2 个移动迭代器    std::move_iteratorbegin = make_move_iterator(myvec.begin());    std::move_iteratorend = make_move_iterator(myvec.end());    //以复制的方式初始化 othvec 容器    vector <:string> othvec(begin.base(), end.base());       cout << "myvec:" << endl;    //输出 myvec 容器中的元素    for (auto ch : myvec) {        cout << ch << " ";    }    cout << endl << "othvec:" << endl;    //输出 othvec 容器中的元素    for (auto ch : othvec) {        cout << ch << " ";    }    return 0;}

程序执行结果为:

myvec:STL Java Pythonothvec:STL Java Python

显然,通过调用 base() 成员方法,初始化 othvec 容器的方式转变为以复制而非移动的方式,因此 myvec 容器不会受到影响。

8ef9a95a7b51bbcabc2ce289d2eefbe2.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前插型迭代器front_insert_iteratorSTL中的一种迭代器类型,用于将元素插入容器的头部而不是尾部。它可以适用于所有支持push_front操作的容器,如list和deque等。 使用前提:需要使用一个支持push_front操作的容器,如list或deque。 定义方法:可以通过以下方式定义一个前插型迭代器front_insert_iterator: ``` template <typename Container> class front_insert_iterator { public: // 构造函数,接受一个容器作为参数 explicit front_insert_iterator(Container& x) : container(&x) {} // 重载运算符* front_insert_iterator& operator*() { return *this; } // 重载运算符++ front_insert_iterator& operator++() { return *this; } // 重载运算符++(后缀) front_insert_iterator operator++(int) { return *this; } // 重载运算符= front_insert_iterator& operator=(const typename Container::value_type& value) { container->push_front(value); return *this; } private: Container* container; }; ``` 其中,Container是容器的类型,value_type是容器中存储的元素类型。通过以上定义,就可以使用front_insert_iterator将元素插入容器的头部了。例如,可以通过以下方式将元素插入list的头部: ``` #include <iostream> #include <list> #include <iterator> using namespace std; int main() { list<int> mylist = {1, 2, 3, 4, 5}; front_insert_iterator<list<int>> myfront(mylist); *myfront = 6; ++myfront; *myfront = 7; for (auto i : mylist) { cout << i << " "; } return 0; } ``` 输出结果为:7 6 1 2 3 4 5。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值