C++Primer第五版 第九章習題答案(31~40)
31:知識點1:容器的改變可能會使迭代器失效,插入和刪除各有其相關的規則,P315.
知識點2:必須保證每次改變容器的操作之後都正確的重新定位迭代器的操作
知識點3:呼叫erase()之後,其返回的迭代器指向的是序列中的下一個元素,其返回的迭代器可以用來更新
知識點4:向容器插入元素後,對於list和forward_list,指向容器的迭代器、指標、引用皆有效
對於list
advance(iter, 2);
對於forward_list
#include<iostream> #include<forward_list> using namespace std; void main() { forward_list<int> vi = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; auto prev = vi.before_begin(); auto curr = vi.begin(); while (curr != vi.end()) if (*curr % 2) { curr = vi.insert_after(prev, *curr); //返回迭代器,指向新插入元素 prev = ++curr; ++curr; } else curr = vi.erase_after(prev); for (auto a : vi) cout << a << ends; cout << endl; system("pause"); }
32:首先明確運算子的順序:++高於*解引用符號。
分析:對於容器vi = {0,1,2,3,4,5,6,7,8,9}; iter = vi.insert(iter,*iter ++); 後置++雖然優先順序高於解引用*,但是iter是拿遞增之前的迭代器去解引用,所以第一次的插入操作vi.insert(iter,*iter ++)中,第二個引數*iter ++ 的結果是1,而第一個引數iter則為遞增之後的迭代器(此時指向2),故應該是在2之前插入1。 但是,返回的是插入元素的迭代器,故,iter又重新指向0,1,1,2,3,4,5,6,7,8,9的第二個1。這樣之後的操作會無限迴圈的再2前面插入1。因此需要手動移動迭代器,程式碼如下:
#include<iostream> #include<list> using namespace std; void main() { list<int> vi = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; auto iter = vi.begin(); while (iter != vi.end()) if (*iter % 2) { iter = vi.insert(iter, *iter++); ++iter; } else iter = vi.erase(iter); for (auto a : vi) cout << a << ends; cout << endl; system("pause"); }
33:知識點:不要儲存end返回的迭代器,因為你對容器的操作會使得這個迭代器失效。(vector,string,deque)
程式會崩潰,因為begin迭代器的值在插入一個元素之後已經失效。
34:老生常談的問題了,insert()返回的迭代器是指向新插入元素的,如若進行插入元素,需要加兩次才能跳過當前元素。
**************************************未完待續***********************************************