千慮一得齋OnLine_觀死書齋-Yahoo/Hexun/Blogger/sina/Xuite

觀死書齋暨Spread、和訊博客全文檢索

2019年10月31日 星期四

C++自修入門實境秀、C++ Primer 5版研讀秀 73/ ~ v11關聯式容器~11.3.3. Erasing Elements





11.3.2. Adding Elements

在關聯式容器中新增元素、加入元素

關聯式容器的加入元素運算(容器運算)



7:10

頁432

Table 11.4. Associative Container insert Operations

表11.4 :關聯式容器的insert運算

c.insert(v) c.emplace(args) v是value_type物件;args用來建構一個元素。對map和set來 說,元素只會在具有給定鏈值的那個元素尚未出現在c中的時候才 會被插入(或建構)。回傳一個pair,其中含有一個迭代器指向具 有給定鍵值的那個元素,以及一個bool指出該元素是否是被插入的→指出該元素是否已被插入。Returns a pair containing an iterator referring to the element with the given key and a bool indicating whether the element was inserted.

對multimap與multiset來說,插入(或建構)所給的元素,並回傳一個迭代器指向新的元素。

c.insert(b, e)

c.insert(il) b和e是代表一個範圍的c::value_type值的迭代器;il(initializer list)是大括號圍起的這種值的一個串列。

il is a braced list of such values.

回傳void。對map和set來說,若鍵值尚未在c中,就插入元素。對multimap與multiset來說, 插入該範圍中的每個元素。

c.insert(p,v)

c.emplace(p, args) 就像insert(v)(或emplace(args)),但使用迭代器p作為一個提示,告知應該從哪裡開始找尋要儲存那個新元素的地方。回傳一個迭代器指向具有給定鍵值的元素。

Like insert (v) (or emplace (args)), but uses iterator p as a hint for where to begin the search for where the new element should be stored. Returns an iterator to the element with the given key.

關聯式容器既然與元素儲存的「位置」無關(頁423),又何故要「where」?!這真的有趣(趣味小品的趣)

50:00 2:29:40



// four ways to add word to word_count

word_count.insert({word, 1});

word_count.insert(make_pair(word, 1));

word_count.insert(pair<string, size_t>(word, 1));

word_count.insert(map<string, size_t>::value_type(word, 1));



學習程式設計之必要

51:20工欲善其事必先利其器 有事弟子服其勞 電子計算機

1:11:33隨便下一個pptx檔來將圖文內容匯出至Word

1:10:20 1:24:59

Word VBA選取區字符汰重(直接刪除重複者)

1:31:30 增修程式碼完成,測試中……

測試成功,效能也提升了! 2:21:00



頁432

Testing the Return from insert

2:38:30

The value returned by insert (or emplace) depends on the container type and the parameters.

對於鍵值不可重複的關聯式容器,(即non-multi)傳回來的pair型別中,第一個成員是表示一個指向被插入元素(鍵值)的迭代器;第二個成員則表示插入是否完成,或已經有相同的鍵值在原容器中了

頁433

Unwinding the Syntax

解讀語法

Adding Elements to multiset or multimap

新增元素到 multiset或multimap

3:9:50

頁434

練習11.20

3:17:10

#include<iostream>

#include<map>

using namespace std;

int main() {

// count the number of times each word occurs in the input

map<string, size_t> word_count; // empty map from string to size_t

string word;

while (cin >> word)

{

pair<map<string, size_t>::iterator, bool> inR = word_count.insert({ word, 1 });

if (!inR.second) ++inR.first->second;

}

//++word_count[word]; // fetch and increment the counter for word

for (const auto& w : word_count) // for each element in the map

// print the results

cout << w.first << " occurs " << w.second

<< ((w.second > 1) ? " times" : " time") << endl;

}

3:26:01

練習11.21

#include<iostream>

#include<map>

using namespace std;

int main() {

// count the number of times each word occurs in the input

map<string, size_t> word_count; // empty map from string to size_t

string word;

while (cin >> word)

++word_count.insert({ word, 0 }).first->second;//其實就是下面(即練習11.20)的濃縮

//while (cin >> word)

//{

// pair<map<string, size_t>::iterator, bool> inR = word_count.insert({ word, 1 });

// if (!inR.second) ++inR.first->second;

//}

//原來的下標(subscript)運算

//++word_count[word]; // fetch and increment the counter for word

for (const auto& w : word_count) // for each element in the map

// print the results

cout << w.first << " occurs " << w.second

<< ((w.second > 1) ? " times" : " time") << endl;

}

3:37:17

練習11.22

#include<iostream>

#include<map>

#include<vector>

using namespace std;

int main() {

map<string, vector<int>> m;

string word;

int i;

vector<int>v;

while (cin >> word)

{

cin >> i;

v.push_back(i);

cin >> i;

pair<map<string, vector<int>>::iterator, bool> insResult =

m.insert(pair<string, vector<int>>(word, v));

if (!insResult.second) insResult.first->second.push_back(i);

//以上3行程式碼可濃縮為下一式

//(m.insert(pair<string,vector<int>>(word,v)).first->second).push_back(i);

}

for (const auto& w : m) // for each element in the map

// print the results

cout << w.first << " occurs " << w.second.back()

<< ((w.second.size() > 1) ? " times" : " time") << w.second.size()<<

endl;

}

4:0:55

練習11.23

練習11.7

#include<iostream>

#include<map>

#include<vector>

#include<iterator>

using namespace std;

int main() {

multimap<string, vector<string>> m;

istream_iterator<string>in(cin), end;

string lastName; vector<string>v;

while (in != end)

{

lastName = *in;

m.insert(pair<string, vector<string>>(lastName, v))->second.push_back(*++in);

++in;

}

ostream_iterator<string>out(cout, ",");

for (auto a : m)

{

cout << a.first << ":";

copy(a.second.cbegin(), a.second.cend(), out);

cout << endl;

}

}

Word VBA 漢字部件數程式碼增修

4:16:00 5:8:00 完成。可以照系統內定的簡化字排序 https://snipsave.com/oscarsun72/#/snippet/QJJh5ASJTQfBeHtYIT

11.3.3. Erasing Elements

11.3.3清除元素

4:15:10

erase()成員函式

和循序容器(sequential container)的操作都很類似

5:11:10

頁435

Table 11.5. Removing Elements from an Associative Container

表11.5 :從一個關聯式容器移除元素

c.erase (k) 從c移除每個具有鍵值k的元素。回傳size_type指出所移除的元素數。

c.erase (p) 從c移除迭代器p所代表的元素。p必須實際指向c中的一個元素;它必須不等於c.end()。回傳一個迭代器指向p後的元素,或在p代表c中最 後一個元素時,回傳c.end()。

c.erase(b, e) 移除迭代器對組b和e所表示的範圍中的元素。回傳e。

正文說不回傳這表卻說回傳:

These versions of erase are similar to the corresponding operations on sequential containers: The indicated element(s) are removed and the function returns void.

11.3.4. Subscripting a map

11.3.4為一個map添標

中文版前均翻成「下標(subscript)」

→對map容器下標(subscript)

2019年10月30日 星期三

【廢課程&雷教授】#文化大學|孫守真?



原影片載: https://youtu.be/I40_MJk4JPE

https://www.youtube.com/channel/UCKGTiVK6ZrsmyoPjqKEOTww

感恩感恩 「廢課程&雷教授」菩薩慈悲 南無阿彌陀佛

這部片我轉載在此,並且作為我頻道的首頁作推廣片喔。如有版權不妥,請即告知,將屏蔽。若蒙不棄,感恩大德為我作嫁,以接引更多真積好學之有緣眾生;也如實反映出臺灣教育現況的科學事實。感恩感恩。南無阿彌陀佛



緣起:

https://www.youtube.com/watch?v=I40_MJk4JPE&lc=UgzZUxzI7nkP4N1Bkh94AaABAg



菩薩慈悲 本尊來補充,歡迎來瞭解。國文在生活,識的沒幾個。具名且露臉,背書又負責。不作遮掩事,人做天知道。感恩感恩 讚歎讚歎 南無阿彌陀佛

學生試題範本:http://bit.ly/2Pg5bJI

歡迎指教考證,不必人云亦云。

有頭有臉有名,不做無名小卒。

教育教出什麼?只會偷偷摸摸

正大光明不做,來生換作什麼

感恩感恩 南無阿彌陀佛



《九陽神功》:http://bit.ly/2AJgyFX

《七星大法》:http://bit.ly/2yQITZF

合為《降龍十八掌》

上課實境秀:

http://bit.ly/2pBKoG1

所有教材講義:

http://bit.ly/2khF8Ic

希望不再只是我讀得懂,賞析得出,也願等到讀得比我懂、賞析比我精的時候,再來高論闊談。青出於藍,民族有望,人類長好。感恩感恩 南無阿彌陀佛

【本留言未獲版主刊出,特誌於此。願所謂的言論自由並不止是一言堂。凡本人一切,人做天看,朗朗乾坤,均可查證,以作為往生資糧。感恩感恩 南無阿彌陀佛】



我如何解讀古文、文言文的方法與技巧

講義下載: 

http://bit.ly/2khF8Ic (全部)

https://1drv.ms/f/s!Ap2-JNk0W_CPoHd5JJyxGybeTuZB (全部)

http://bit.ly/2AJgyFX (九陽神功、九陰真經、十全大補丸示例)

http://bit.ly/2yQITZF (七星大法示例 )

https://1drv.ms/i/s!Ap2-JNk0W_CPoS0g40Ac785RlGlH(七星大法 png原圖檔 )

http://bit.ly/2wBvWjb

(解讀技巧與方法_上課用_孫守真字任真.pdf)

 

 

字形結構兼音義:音變或聲變線索筆記-隨時想到隨時記,上課方便,逢源不欠

https://1drv.ms/x/s!Ap2-JNk0W_CPxzewa0Zz0yPkuXzN

http://bit.ly/2EXa2ec

 

古文共欣賞(文言文學堂)

https://www.facebook.com/ChineseAndMe

 

匿名留言可到:

https://www.facebook.com/ChineseAndMe/posts/969755276384423

http://sunschinese.blogspot.tw/2014/09/blog-post.html?spref=fb

 


2019年10月23日 星期三

【廢課程&雷教授】#文化大學|孫守真?



菩薩慈悲 本尊來補充,歡迎來瞭解。國文在生活,識的沒幾個。具名且露臉,背書又負責。不作遮掩事,人做天知道。感恩感恩 讚歎讚歎 南無阿彌陀佛

學生試題範本:http://bit.ly/2Pg5bJI
歡迎指教考證,不必人云亦云。
有頭有臉有名,不做無名小卒。
教育教出什麼?只會偷偷摸摸
正大光明不做,來生換作什麼
感恩感恩 南無阿彌陀佛


《九陽神功》:http://bit.ly/2AJgyFX
《七星大法》:http://bit.ly/2yQITZF
合為《降龍十八掌》
上課實境秀:
http://bit.ly/2pBKoG1
所有教材講義:
http://bit.ly/2khF8Ic
希望不再只是我讀得懂,賞析得出,也願等到讀得比我懂、賞析比我精的時候,再來高論闊談。青出於藍,民族有望,人類長好。感恩感恩 南無阿彌陀佛



2019年10月3日 星期四

C++自修入門實境秀、C++ Primer 5版研讀秀 55/ ~9.3.1. Adding Elements to a Sequential ...





9.2.5. Assignment and swap

9.2.5指定和swap(對調)

c1 = {a,b,c}; // after the assignment c1 has size 3

指定後會改變容器的大小(會縮小不會變大)

If the containers had been of unequal size, after the assignment both containers would have the size of the right-hand operand.

14:00



頁338

Unlike built-in arrays, the library array type does allow assignment. The left-and right-hand operands must have the same type:

不能用中括弧的串列去指定array容器:

array<int, 10> a1 = {0,1,2,3,4,5,6,7,8,9};

array<int, 10> a2 = {0}; // elements all have value 0

a1 = a2; // replaces elements in a1

a2 = {0}; // error: cannot assign to an array from a braced list

因為大小是array型別的一部分,所以要指定的話,必須兩邊一致,所以「same type」即是元素型別和多少是一樣的:

Because the size of the right-hand operand might differ from the size of the left-hand operand, the array type does not support assign and it does not allow assignment from a braced list of values.



Table 9.4. Container Assignment Operations

容器型別關於指定操作的運算

表9.4 :容器的指定運算

c1 = c2 將c1中的元素取代為c2中元素的拷貝。c1和c2必須有相同型別。

c = {a, b, c … } 以初始器串列中元素的拷貝來取代c1中的元素。(對array無效)

swap (c1, c2) 將c1中的元素與c2中的元素互換。c1和c2必須是相同型別。Exchanges elements in cl with those in c2. cl and c2 must be the same type,

c1.swap(c2) swap通常會比從c2到cl拷貝元素還要快很多。

swap is usually much faster than copying elements from c2 to c1.

assign運算對關聯式容器或array來說無效

seq.assign(b,e) 將seq中的元素以迭代器b和e所代表的元素取代。迭代器b和e不 可以指向seq中的元素。

seq.assign(il) 以初始器串列il中的元素取代seq中的元素。

seq.assign(n,t) 以值為t的n個元素取代seq中的元素。

il,應是initializer list之意(果然,見頁344 The versions of insert that take a pair of iterators or an initializer list insert the elements from the given range before the given position:。第55集 7:38:20

seq,即循序容器(sequential container)之縮寫



WARNING:

Assignment related operations invalidate iterators, references, and pointers into the left hand container.

Aside from string they remain valid after a swap, and (excepting arrays) the containers to which they refer are swapped.

和指定assignment ⑦先抓動詞 ⑧找對主詞 相關的運算會使指向左手邊容器的迭代器、參考,以及指標無效化。

不過string在swap之後還是有效,而(除了array外),它們所指的容器會被對調。

1:17:54 中文版又翻錯了!(參見下頁 )這前面講的是assign,後面講的是swap,分屬兩個成員、方法,不可混同!assign後,原迭代器、指標、參考均會失效,但swap後,它們仍然有效,只有在string這樣的容器被swap後才會失效。它們不但在swap後仍然有效,且指向的容器會被對調(除了array這樣的容器例外)。

36:00

Using assign (Sequential Containers Only)

使用assign (僅限循序容器)

這個assign是指方法(循序容器的成員函式)

44:00

頁339

// equivalent to slist1.clear();

// followed by slist1.insert(slist1.begin(), 10, "Hiya!");

list<string> slist1(1); // one element, which is the empty string

slist1.assign(10, "Hiya!"); // ten elements; each one is Hiya !

可見assign方法(成員函式)可以重新定義或調整容器的大小(元素的多少)的

55:30

Using swap

使用 swap方法(即「成員函式」)

其實是對調二個容器內部的資料結構,並不是對其元素的處理

相同型別的容器才能用 swap

After the call to swap , the elements in the two containers are interchanged:

swap (c1, c2)



c1.swap(c2)

第一個應是容器類別的介面函式,而第二種是容器類別型別物件的成員函式(即「方法」)(果然,詳下頁339)



swap is usually much faster than copying elements from c2 to c1.

With the exception of array s, swapping two containers is guaranteed to be fast—the elements themselves are not swapped; internal data structures are swapped.

除了 array這個例外,對調兩個容器的動作保證會很快速,元素本身不會對調,互換的是內部的資料結構。

正是因為只有對調資料結構,所以速度才快

swap時間(耗時)沒有快慢之分:

Note: Excepting array, swap does not copy, delete, or insert any elements and is guaranteed to run in constant time.

其所需的時間是固定的

The fact that elements are not moved means that, with the exception of string, iterators, references, and pointers into the containers are not invalidated. They refer to the same elements as they did before the swap. However, after the swap, those elements are in a different container. For example, had iter denoted the string at position svec1 [3] before the swap, it will denote the element at position svec2[3] after the swap.

Differently from the containers, a call to swap on a string may invalidate iterators, references and pointers.

不同於其他容器→和這些容器不同,在一個string上呼叫swap 會使迭代器、參考和指標無效化。

用into大概是因為若用to,就成了指向容器本身,而若用「in」則成了在容器中的元素本身,都不是。所以用into,即指向容器中的元素的指標、參考與迭代器。

1:36:00

Unlike how swap behaves for the other containers, swapping two array s does exchange the elements.

其他容器swap只是對調容器,並不會動到元素;而array這樣的容器swap後是真的會動到它的元素。因此,對調(swap)兩個array這樣的容器所需的時間,就看它們的元素多少來決定

只有string例外,swap後,所有和元素有關的,諸如迭代器、指標、參考都仍有效,且仍然指向同一個「東西」(元素)。這裡是專就array談,但其他容器,除了string也類似:

After the swap , pointers, references, and iterators remain bound to the same element they denoted before the swap . Of course, the value of that element has been swapped with the corresponding element in the other array .

所以array和其他容器在做swap的時候也類似,只是因為實際上在行動元素,所以花的時間,就不像其他容器是恆定的了。

1:49:50

In the new library, the containers offer both a member and nonmember version of swap .

這就是我們之前提到的介面函式(nonmember)和成員函式的swap

非成員的swap在泛型程式中最為重要。就習慣而言,最好是使用非成員版的swap。

習慣上,最好使用swap的非成員版本。(google翻譯)

頁340

練習9.14

1:55:59

2:23:20 忘了按暫停!

C式的字元字串,其實就是char的陣列(字元陣列(character arrays)

C-Style的字元字串

Strings that follow this convention are stored in character arrays and are null terminated.(頁122)

#include<vector>

#include<string>

#include<list>

using namespace std;



int main() {

vector<string > vecs{"孫守真","文天祥","顧炎武"};

char ca[] = "abcde";

list<char*> lstcp(10,ca);

vecs.assign(lstcp.cbegin(),lstcp.cend());//相當於下式

//vecs.clear(); vecs.insert(vecs.cbegin(), lstcp.size(), *(lstcp.begin()));

}

or

const char ca[] = "abcde";

list<const char*> lstcp(10,ca);

4:8:38

9.2.6. Container Size Operations

和容器大小相關的運算有三個成員函式 size()、empty() and max_size():

and max_size returns a number that is greater than or equal to the number of elements a container of that type can contain.

也就是那個型別容器能容下的最大數,應該和Visual Studio 2019 中所顯示時capacity()方法(成員函式)是不一樣的

只有 forward_list只提供了兩種關於容器大小的運算(沒有.size())。

9.2.7. Relational Operators

這一段是談各容器間的大小關係是如何計算的

4:16:59

關係運算子

所有的容器(包括關聯式容器(associative container)都支援相等性運算子(==、!=),而除了無序的關聯式容器(unordered associative containers)外,都支援關係運算子(relational operator:>,>=,<,<=)

關係運算子的兩端運算元一定要同型別的容器,且有同型別的元素

容器與元素型別均同才能作關係比較

逐對比較(pairwise comparison)

就是一個元素與其對應位置的元素(corresponding element)作比較

初始子序列(initial subsequence)

4:32:20

意指一開始的元素(即[0])就相同的子序列

vector<int> v1 = { 1, 3, 5, 7, 9, 12 };

vector<int> v2 = { 1, 3, 9 };

vector<int> v3 = { 1, 3, 5, 7 };

vector<int> v4 = { 1, 3, 5, 7, 9, 12 };

v1 < v2 // true; v1 and v2 differ at element [2]: v1[2] is less than v2[2]

v1 < v3 // false; all elements are equal, but v3 has fewer of them;

v1 == v4 // true; each element is equal and v1 and v4 have the same size()

v1 == v2 // false; v2 has fewer elements than v1

v3就是v1的初始子序列(initial subsequence)



頁341

Relational Operators Use Their Element’s Relational Operator

關係運算子會使用它們元素的關係運算子

⑧找對主詞

Containers’ Relational Operators Use Their Element’s Relational Operator

只能在其元素型別有適當的比較運算子存在時才能利用容器的比較運算子(關係運算子(relational operator))

因為比較兩個容器是一定要用到元素比較的!

物有本末,事有終始;知所先後,則近道矣

For example, the Sales_data type that we defined in Chapter 7 does not define either the == or the < operation. Therefore, we cannot compare two containers that hold Sales_data elements:


4:45:07

練習9.15

#include<vector>

#include<iostream>

using namespace std;

bool equal2containers(vector<int>veci1, vector<int> veci2) {

if (veci1.size() == veci2.size())

{

vector<int>::size_type sz{0};

for(int var : veci1){

if (var != veci2[sz])

return false;

++sz;

}

return true;

}

return false;

}

int main() {

vector<int>veci1{2,3,4,4,5};

vector<int>veci2{2,3,4,4,5};

cout<<equal2containers(veci1, veci2)<<endl;

}



4:55:50

練習9.16

#include<string>

#include<vector>

#include<list>

#include<iostream>

using namespace std;

string compareElements(list<int>lsti, vector<int> veci) {

if (lsti.empty() || veci.empty()) return "請傳入有效容器!";

vector<int>::size_type sz{0};

for (int var : lsti) {

if (var > veci[sz])

return "list 大於 vector";

else if (var < veci[sz])

{

return "list 小於 vector";

}

else

{

++sz;

if (sz > (veci.size() - 1))

if(lsti.size() !=veci.size())

return "list 元素多於 vector,且vector是list的初始子序列(initial subsequence)";

else

return "list 等於 vector";

}

}

if (lsti.size()<veci.size())

{

return "list 是 vector的初始子序列(initial subsequence)";

}

else

return "list 等於 vector";

}



int main() {

list<int>lsti{2,3,4,4,5};

vector<int>veci2{2,3,4,4,5};

cout<<compareElements(lsti, veci2)<<endl;

}

5:24:50

練習9.17

1)不能是無序的關聯式容器(unordered associative containers)

2)容器型別與元素型別必須皆一致

5:28:50

9.3. Sequential Container Operations

9.3循序容器的運算

循序容器(sequential container)與關聯式容器(associative container)的不同在於對其元素組織布排的方式:

The sequential and associative containers differ in how they organize their elements. These differences affect how elements are stored, accessed, added, and removed.

接下來都將會專門討論循序容器的運算

5:33:50

9.3.1. Adding Elements to a Sequential Container

在一個循序容器中加入元素

除了array這樣的容器,程式庫型別的容器都可以在執行階段動態地改變容器的大小:

Excepting array , all of the library containers provide flexible memory management. We can add or remove elements dynamically changing the size of the container at run time.

vector、string如果不是在尾端加入元素,deque若不是在首尾兩端加入元素,那麼就必須行動其他被影響的元素,來容納新加入的元素。因此就有效能問題了。

對vector或string容器加入元素也可能需要整個物件重新配置記憶體空間。所有的元素都必須從原位,移動到新的記憶體位置

頁342

6:13:30 6:17:33

Visual Studio 2019 與 github的操作

刪除本地冗餘的檔案,再push到github,GitHub上才不會在每個分支(branch)上殘留太多複不必要的檔案,而需要的檔案,仍會保留在相對應的鍛(branch)中,只要切換branch就會與Github上的同步

Using push_back

6:29:49 6:31:00

Because string is just a container of characters, we can use push_back to add characters to the end of the string :

注意:是加「字元(字符,character)」不是加「字串(string)」

void pluralize(size_t cnt, string &word) {

if (cnt > 1) word.push_back(' s '); // same as word += 's'

}



6:41:00

Key Concept: Container Elements Are Copies

When we use an object to initialize a container, or insert an object into a container, a copy of that object’s value is placed in the container, not the object itself.

關鍵概念:容器元素是拷貝→重要觀念:容器元素只是副本/複本

不是它自己放到容器中,而是它的版本放進容器中,因此,如果有對該物件(東西)的參考、指標等等,一樣沒變。

Using push_front

頁343

6:46:30

push_front只適用在list forward_list deque

deque不管頭尾插入元素都一樣快

如果不在頭尾兩端插入新元素,則deque和vector一樣,都會較為耗時、效能較低:

As with vector, inserting elements other than at the front or back of a deque is a potentially expensive operation.

就跟vector —樣,在一個deque的前端或後端以外的地方插入元素很可能會是昂貴的運算。

昂貴的運算→這是哪一國的中文?



5:40:22

Table 9.5. Operations That Add Elements to a Sequential Container

表9.5 :新增元素到一個循序容器的運算

這些運算會改變容器的大小;array沒有支援它們。

forward_list 有特殊版本的 insert 和 emplace,請參閱 § 9.3.4。

push_back 和emplace_back 對 forward_list 來說無效。

push_front 和 emplace_front 對 vector 或 string 來說無效。

c.push_back(t) c.emplace_back (args) 在c的後端(back)創建具有值t的元素或從args建構出來的元素。回傳void 。

c.push_front(t) c.emplace_front(args) 在c的前端(front)創建具有值t的元素或從args建構出來的元素。回傳void 。

c. insert(p,t) c.emplace(p, args) 在迭代器p所代表的元素前創建一個具有值t的元素或從args 建構出來的元素。回傳一個迭代器指向被新增的那個元素。Creates an element with value t or constructed from args before the element denoted by iterator p. Returns an iterator referring to the element that was added.

c.insert(p,n,t) 在迭代器p所表示的元素前插入n個具有值t的元素。回傳一個 迭代器指向所插入的第一個元素;如果n為零,就回傳p。

c.insert(p,b,e) 在迭代器p代表的元素前插入迭代器b和e表示的範圍中的元素。 b和e不可以指向c中的元素。回傳一個迭代器指向所插入的第 一個元素;如果範圍是空的,就回傳p。

c.insert(p,il) il(initializer list)是由大括號圍起的元素值串列。在迭代器p所代表的元素前 插入所給定的值。回傳一個迭代器指向第一個插入的元素;如果 串列是空的,就回傳P 。



Returns an iterator referring to the element that was added.

回傳一個迭代器指向被新增的那個元素→回傳一個指向新增元素的迭代器。



WARNING:

新增元素到一個vector、string或deque可能會使容器所有既存的迭代器、參考和指標都無效化。

無效化→失效

言下之意難道是list和forward_list不會失效?

7:1:20

Adding Elements at a Specified Point in the Container

The insert members are supported for vector , deque , list , and string . forward_list provides specialized versions of these members that we’ll cover in § 9.3.4 (p. 350 ).

因為要指定位置(插入點):

Each of the insert functions takes an iterator as its first argument.

所有可以是迭代器的位置都可以。

會從這個迭代器引數指向的位置前插入元素

slist.insert(iter, "Hello!"); // insert "Hello!" just before iter

頁344

即使某些容器是不提供push_front的運算,但是若是在它們身上用instert,也沒有類似的限制(即可以在其前端插入新元素):

Even though some containers do not have a push_front operation, there is no similar constraint on insert .

然而即使可以在vector前端insert新元素,但也別忘了,只要不是在vector的尾端插入新元素,其效能都是很差的

7:19:00

Warning: It is legal to insert anywhere in a vector, deque , or string . However, doing so can be an expensive operation.

在一個vector、deque或string的任何地方插入元素都是合法的。然而,這麼做 有可能會是昂貴的運算。

雖然在vector、deque、string的任何一個位置插入新元素都是可以的,但只要不是在尾端(vector string)或在首尾兩端(deque)插入,都須付出一定的/可觀的代價

7:23:20

Inserting a Range of Elements

insert引數,在最前面的迭代器引數後接的是一個類似容器建構器的引數:

The arguments to insert that appear after the initial iterator argument are analogous to the container constructors that take the same parameters.

這個引數是和那種建構器一樣,帶了一個元素量和一個元素值的兩個引數(參數)

The version that takes an element count and a value adds the specified number of identical elements before the given position:

The version這種版本的insert,會在第一個引數迭代器指定的位置前插入這樣的元素量與元素值。



7:45:00

insert如果帶有要插入元素範圍的引數,那麼就會回傳迭代器。若插入成功,則回傳插入範圍元素的第一個元素的迭代器,否則就回傳insert的第一個引數的迭代器。

7:48:10

頁345

Using the Return from insert

怎麼運用insert回傳的值

list<string> 1st; auto iter = 1st.begin(); while (cin >> word) iter = 1st.insert(iter, word); // same as calling push_front

利用insert的回傳迭代器,我們可以再代入insert成員函式中,作為第一個引數,在同一個指定處而插入元素

list<string> 1st;

auto iter = 1st.begin();

while (cin >> word)

iter = 1st.insert(iter, word); // same as calling push_front

7:57:40

Using the Emplace Operations

新標準引進了3個新成員:

emplace

emplace_front

emplace_back

這三個是建構新元素,而不是拷貝元素

這樣的運算,是為了與insert、push_front、push_back相對應的

當調用emplace這組操作時,是傳遞了想要建構的元素型別的建構器所需的引數:

When we call an emplace member, we

pass arguments to a constructor for the element type.

The emplace members use those arguments to construct an element directly in space managed by the container.

emplace成員使用那些引數直接在容器所管理的空間中建構一個元素。

「建構、構建」皆可

// construct a Sales_data object at the end of c

// uses the three-argument Sales_data constructor

c.emplace_back("978-0590353403", 25, 15.99);

// error: there is no version of push_back that takes three arguments

c.push_back("978-0590353403", 25, 15.99);

// ok: we create a temporary Sales_data object to pass to push_back

c.push_back(Sales_data("978-0590353403", 25, 15.99));



emplace這組成員函式的引數,是看要建構的元素型別而定的,而不是固定的哪些引數:

The arguments to an emplace function vary depending on the element type.

其引數必須匹配該元素型別的某個建構器

其引數當然就必須要和要建構的元素型別它的建構器所需的引數能符合

頁346

8:18:55

// iter refers to an element in c, which holds Sales_data elements

c.emplace_back(); // uses the Sales_data default constructor,因為預設建構器是不帶引數的

c.emplace(iter, "999-999999999"); // uses Sales_data(string):在做函式匹配(function matching)

// uses the Sales_data constructor that takes an ISBN, a count, and a price

c.emplace_front("978-0590353403", 25, 15.99);

練習9.18

8:24:35

#include<string>

#include<deque>

#include<iostream>

using namespace std;

void read() {

string word;

deque<string> deqstr;

while (cin>>word)

{

deqstr.push_back(word);

}

for(deque<string>::const_iterator iter=deqstr.cbegin();iter != deqstr.cend();++iter)

cout << *iter << endl;

}



int main() {

read();

}

8:42:38

練習9.19

#include<string>

#include<list>

#include<iostream>

using namespace std;

void read() {

string word;

list<string> deqstr;

while (cin>>word)

{

deqstr.push_back(word);

}

for(list<string>::const_iterator iter=deqstr.cbegin();iter != deqstr.cend();++iter)

cout << *iter << endl;

}



int main() {

read();

}

8:50:43

練習9.20

#include<deque>

#include<list>

using namespace std;

void copyElements() {

list<int>lsti{1,3,2,4,7,8,9,10,111};

deque<int>deqiEven;

deque<int>deqiOdd;

for (list<int>::const_iterator iter = lsti.cbegin(); iter != lsti.cend(); ++iter)

{

int i = *iter;

if (i % 2 == 0)

{

deqiEven.push_back(i);

}

else

deqiOdd.push_back(i);

}

}



int main() {

copyElements();

}

9:1:10

練習9.21

#include<string>

#include<vector>

#include<iostream>

using namespace std;

int main() {

string word;

vector < string> lst;

auto iter = lst.begin();

while (cin >> word)

iter = lst.insert(iter, word); // same as calling push_front



/*string word;

list < string> lst;

auto iter = lst.begin();

while (cin >> word)

iter = lst.insert(iter, word); // same as calling push_front

*/

}

9:13:29

練習9.22

#include<string>

#include<vector>

#include<iostream>

using namespace std;

int main() {

int some_val=10;

vector<int>iv{2,4,6,8,10,12,14,25,33,1};

vector<int>::iterator iter = iv.begin(),

mid = iv.begin() + iv.size() / 2;

while (iter != mid)

{

if (*iter == some_val)

{

iter = iv.insert(iter, 2 * some_val);//在vector插入元素後,它元素的迭代器會失效,所以「mid」 也會失效

//break;//此下二行均可無誤地離開迴圈

mid = iv.begin() + iv.size() / 2;

}

++iter;

}

}