插入迭代器inserter在copy函數的運行機制是什麼?

list& lst={1,2,3,4};

list& lst2, lst3;

copy(lst.cbegin(),lst.cend(),front_inserter(lst2));//lst2包含 4 3 2 1

copy(lst.cbegin(),lst.cend(),inserter(lst3,lst3.begin()));//lst3包含 1 2 3 4

inserter會調用lst3.insert(),這裡lst3應該是先把第一個元素拷貝進去,然後它就成為了首元素,再插入應該會插入首元素之前啊,也就是lst3應該也是4 3 2 1,

但是結果是1 2 3 4

啊啊我明白了,inserter會返回一個迭代器,這個迭代器指向的並不是剛插入的元素,插入元素之後的那個元素,這樣就可以繼續迭代了~


我認為front_inserter / inserter的意思應該是push_front和push_back。


這是copy的源碼:

template&
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
{
while (first!=last) {
*result = *first;
++resu< ++first; } return resu< }

這是insert_iterator的相關源碼:

insert_iterator& operator= (typename Container::value_type value)
{ iter=container-&>insert(iter,std::move(value)); ++iter; return *this; }
insert_iterator& operator* ()
{ return *this; }
insert_iterator& operator++ ()
{ return *this; }

copy(lst.cbegin(),lst.cend(),inserter(lst3,lst3.begin()));
相當於:

first = lst.cbegin();
last = lst.cend();
result = inserter(lst3,lst3.begin());
while (first!=last) {
*result = *first;
++resu< ++first; }

*result = *first;

這一行會使用到operator* 這個「*」重載操作符,返回的是*this。並且會使用到operator = 這個「=」的重載操作符。

這個「=」的操作符會通過list容器的iterator insert (const_iterator position, const value_type val)成員函數插入元素的值,並將新的待插入的位置賦值給iter(也就是相當於接下來的元素可以插入的位置,是list中剛才插入的元素的下一個位置),返回值就是An iterator that points to the first of the newly inserted elements.

所以其實就是如輪子哥所說,一直在「push_back」。


C++ Primer 5th,p358對這個問題有較詳細解釋.

書上有句:元素將被插入到給定迭代器所表示的元素之前(這句話很會被誤解)

我的理解是inserter將元素分成容器本身(舊元素)存在的元素和新插入的元素,比如插入1後,再插入2,分為新插入的元素1和本身存在的元素(也就是空),此時copy(lst.cbegin(),lst.cend(),inserter(lst3,lst3.begin()));這裡的lst3.begin()是指向舊元素的迭代器,所以就是1 2而不是2 1。

按輪子哥的理解就更加簡單明了。不知道我的理解是否有誤 @vczh ?


inserter(lst3,lst3.begin())

用lst3.begin()初始化了inserter,然後添加了之後。

inserter還是那個inserter

begin已不是那個begin


inserter的工作過程寫的很清楚啊,先調用insert()函數,再遞增insert()返回的迭代器。這導致inserter迭代器永遠指向初始給的那個元素。 代碼中lst3.begin()只是用來初始化inserter的,不是每次插入都重新初始化一次。你可以寫一個auto iter = lst3.begin(),然後把copy中的lst3.begin()換成iter,這樣好理解


去看文檔啊,寫的清清楚楚呢~


以下引用自sherlly666的博客:

除了普通迭代器,C++標準模板庫還定義了幾種特殊的迭代器,分別是插入迭代器、流迭代器、反向迭代器和移動迭代器,定義在&頭文件中,下面主要介紹三種插入迭代器(back_inserter,inserter,front_inserter)的區別。

首先,什麼是插入迭代器?插入迭代器是指被綁定在一個容器上,可用來向容器插入元素的迭代器。

back_inserter:創建一個使用push_back的迭代器。

inserter:此函數接受第二個參數,這個參數必須是一個指向給定容器的迭代器。元素將被插入到給定迭代器所表示的元素之前。

front_inserter:創建一個使用push_front的迭代器(元素總是插入到容器第一個元素之前)。

list& lst = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
list& lst2 ={10}, lst3={10},lst4={10};
copy(lst.cbegin(), lst.cend(), back_inserter(lst2));
//lst2包含10,1,2,3,4,5,6,7,8,9
copy(lst.cbegin(), lst.cend(), inserter(lst3, lst3.begin()));
//lst3包含1,2,3,4,5,6,7,8,9,10
copy(lst.cbegin(), lst.cend(), front_inserter(lst4));
//lst4包含9,8,7,6,5,4,3,2,1,10


推薦閱讀:

在C#中,如何實現跟native dll 中途的線程間通信?
編程中你們都習慣怎麼使用大括弧?
如何解決光線跟蹤中浮點數誤差導致的渲染錯誤?
既然建議盡量避免使用goto語句為何C++還要支持goto呢?
主推 iOS 但是考慮跨平台,可否跳過 Objective-C 而直接學 C++ 和 Cocos2d-X 呢?

TAG:編程語言 | 編程 | 程序 | C | CPrimer |