C++ list(STL list)增加和插入元素詳解(insert成員函數插入元素)

2020-07-16 10:05:22
可以使用 list 容器的成員函數 push_front() 在它的頭部新增一個元素。呼叫 push_back() 可以在 list 容器的末尾新增一個元素。在下面這兩個範例中,引數作為物件被新增:
std::list<std::string> names { "Jane", "Jim", "Jules", "Janet"};
names.push_front("Ian"); // Add string ("Ian") to the front of the list
names.push_back("Kitty"); // Append string ("Kitty") to the end of the list
這兩個函數都有右值參照引數的版本,這種版本的函數會移動引數而不是從引數複製新的元素。它們顯然要比其他使用左值參照引數的版本高效。然而,成員函數 emplace_front() 和 emplace_back() 可以做得更好:
names.emplace_front("Ian");//Create string ("Ian") in place at the front of the list
names.emplace_back("Kitty");// Create string ("Kitty") in place at the end of the list
這些成員函數的引數是呼叫以被生成元素的建構函式的引數。它們消除了 push_front() 和 push_back() 不得不執行的右值移動運算。

可以使用成員函數 insert() 在 list 容器內部新增元素。像其他序列容器一樣,它有三個版本。

1) 可以在疊代器指定的位置插入一個新的元素:
std::list<int> data(10, 55); // List of 10 elements with value 55
data.insert(++begin(data), 66); // Insert 66 as the second element
insert() 的第一個引數是一個指定插入點的疊代器,第二個引數是被插入的元素。begin() 返回的雙向疊代器自增後,指向第二個元素。上面的語句執行完畢後,list 容器的內容如下:
55 66 55 55 55 55 55 55 55 55 55

list 容器現在包含 11 個元素。插入元素不必移動現有的元素。生成新元素後,這個過程需要將 4 個指標重新設為適當的值。第一個元素的 next 指標指向新的元素,原來的第二個元素的 pre 指標也指向新的元素。新元素的 pre 指標指向第一個元素,next 指標指向序列之前的第二個元素。和 vector、deque 容器的插入過程相比,這個要快很多,並且無論在哪裡插入元素,花費的時間都相同。

2) 可以在給定位置插入幾個相同元素的副本:
auto iter = begin(data);
std::advance(iter, 9); // Increase iter by 9
data.insert(iter, 3, 88);// Insert 3 copies of 88 starting at the 10th
iter 是 list<int>::iterator 型別。insert() 函數的第一個引數是用來指定插入位置的疊代器,第二個引數是被插入元素的個數,第三個引數是被重複插入的元素。為了得到第 10 個元素,可以使用定義在 iterator 標頭檔案中的全域性函數 advance(),將疊代器增加 9。只能增加或減小雙向疊代器。因為疊代器不能直接加 9,所以 advance() 會在迴圈中自增疊代器。

執行完上面的程式碼後,list 容器的內容如下:
55 66 55 55 55 55 55 55 55 88 88 88 55 55

現在 list 容器包含 14 個元素。下面展示如何將一段元素插入到data列表中:
std::vector<int> numbers(10, 5)/ // Vector of 10 elements with value 5
data.insert(--(--end(data)), cbegin(numbers), cend(numbers));
insert() 的第一個引數是一個疊代器,它指向 data 的倒數第二個元素。第二和第三個引數指定了 number 中被插入元素的範圍,因此從 data 中倒數第二個元素開始,依次插入 vector 的全部元素。程式碼執行後,data 中的內容如下:
55 66 55 55 55 55 55 55 55 88 88 88 5 5 5 5 5 5 5 5 5 5 55 55

list 容器現在有 24 個元素。從 numbers 中倒數第二個元素的位置開始插入元素,list 最右邊兩個元素的位置被替換了。儘管如此,指向最後兩個元素的任何疊代器或結束疊代器都沒有失效。list 元素的疊代器只會在它所指向的元素被刪除時才會失效。

3) 有三個函數可以在 list 容器中直接構造元素:emplace() 在疊代器指定的位置構造一個元素;emplace_front() 在 list 的第一個元素之前構造元素;emplace_back() 在 list 的尾部元素之後構造元素。下面是一些用法範例:
std::list<std:: string> names {"Jane", "Jim", "Jules", "Janet"};
names.emplace_back("Ann");
std:: string name ("Alan");
names.emplace_back(std::move(name));
names.emplace_front("Hugo");
names.emplace(++begin(names), "Hannah");

第 4 行程式碼用 std::move() 函數將 name 的右值參照傳入 emplace_back() 函數。這個操作執行後,names 變為空,因為它的內容已經被移到 list 中。執行完這些語句後,names 中的內容如下:
"Hugo” "Hannah" "Jane" "Jim" "Jules" "Janet" "Ann" "Alan"