什么是list
在C++標(biāo)準(zhǔn)庫中,std::list
是一個(gè)雙向鏈表容器,用于存儲(chǔ)一系列元素。與 std::vector
和 std::deque
等容器不同,std::list
使用鏈表的數(shù)據(jù)結(jié)構(gòu)來組織元素,因此在某些操作上具有獨(dú)特的優(yōu)勢和性能特點(diǎn)。以下是關(guān)于 std::list 的詳細(xì)介紹:
特點(diǎn)和優(yōu)勢
雙向鏈表結(jié)構(gòu):
std::list
內(nèi)部使用雙向鏈表來存儲(chǔ)元素。這意味著在插入和刪除元素時(shí),不會(huì)引起其他元素的內(nèi)存重新分配和復(fù)制,因此在這些操作上具有常數(shù)時(shí)間復(fù)雜度。
插入和刪除操作效率高: 由于鏈表結(jié)構(gòu),插入和刪除元素的操作效率非常高。對(duì)于大量的插入和刪除操作,std::list 往往比其他容器更具優(yōu)勢。
迭代器的穩(wěn)定性: 在std::list
中,插入和刪除元素不會(huì)使迭代器失效,除非刪除的正是迭代器所指向的元素。這使得在遍歷過程中進(jìn)行插入和刪除操作更加方便和安全。
空間占用:std::list
每個(gè)元素都需要存儲(chǔ)一個(gè)指向前后元素的指針,因此相對(duì)于數(shù)組型的容器,std::list
的空間占用會(huì)更高。
基本操作
push_back()
和push_front()
: 在鏈表的末尾和開頭插入元素。pop_back()
和pop_front()
: 刪除鏈表的末尾和開頭的元素。insert()
: 在指定位置插入元素。erase()
: 刪除指定位置的元素。begin()
和end()
: 返回指向鏈表起始元素和尾部元素后一個(gè)位置的迭代器。size()
: 返回鏈表中的元素?cái)?shù)量。empty()
: 檢查鏈表是否為空。clear()
: 清空鏈表中的所有元素。
示例用法
#include <iostream>
#include <list>
int main() {
std::list<int> myList;
myList.push_back(1);
myList.push_back(2);
myList.push_back(3);
myList.pop_front();
myList.insert(std::next(myList.begin()), 4);
for (const auto& num : myList) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在使用 std::list
時(shí),需要權(quán)衡其優(yōu)勢和劣勢,根據(jù)實(shí)際場景來選擇合適的容器。當(dāng)需要頻繁插入和刪除元素,且不需要隨機(jī)訪問時(shí),std::list
可能是一個(gè)很好的選擇。但需要注意的是,由于鏈表的特性,std::list
并不適用于需要快速隨機(jī)訪問元素的場景,因?yàn)樵L問某個(gè)位置的元素需要遍歷鏈表。
與其他序列式容器(如 std::vector 和 std::deque)相比,std::list 顯著的區(qū)別和優(yōu)勢
優(yōu)勢:
插入和刪除效率高: 由于
std::list
是雙向鏈表,插入和刪除操作在常數(shù)時(shí)間內(nèi)完成,不需要涉及內(nèi)存的重新分配和元素的復(fù)制。這使得std::list
在大量插入和刪除操作時(shí)非常高效。
迭代器的穩(wěn)定性:std::list
的插入和刪除操作不會(huì)使迭代器失效,除非刪除的正是迭代器所指向的元素。這使得在遍歷過程中進(jìn)行插入和刪除操作更加方便和安全。
空間占用相對(duì)穩(wěn)定:std::list
的空間占用相對(duì)穩(wěn)定,插入和刪除操作不會(huì)影響其他元素的空間占用。
劣勢:
不支持隨機(jī)訪問: 由于鏈表的結(jié)構(gòu),
std::list
不支持像數(shù)組一樣的隨機(jī)訪問。訪問某個(gè)位置的元素需要從鏈表的開頭或結(jié)尾開始遍歷。
額外的指針開銷:std::list
中的每個(gè)元素都需要存儲(chǔ)指向前后元素的指針,這使得空間占用相對(duì)其他容器更高。
緩存效率低: 由于鏈表中元素在內(nèi)存中的存儲(chǔ)位置不連續(xù),導(dǎo)致在訪問鏈表元素時(shí),緩存命中率較低,可能影響性能。
迭代器的使用限制:std::list
的迭代器不支持與普通指針類似的算術(shù)操作(如 + 和 -),因此無法像std::vector
那樣靈活地進(jìn)行迭代器操作。
成員類型
list構(gòu)造函數(shù)
當(dāng)使用 std::list
類創(chuàng)建對(duì)象時(shí),可以使用不同的構(gòu)造函數(shù)來滿足不同的初始化需求。下面詳細(xì)介紹每個(gè)構(gòu)造函數(shù)及其使用示例:
1. default (1)
這個(gè)構(gòu)造函數(shù)用于創(chuàng)建一個(gè)空的 std::list
容器。它可以接受一個(gè)可選的分配器參數(shù),用于指定內(nèi)存分配策略。
std::list<int> myList; // 創(chuàng)建一個(gè)空的 std::list 容器
2. fill (2)
這個(gè)構(gòu)造函數(shù)用于創(chuàng)建一個(gè)包含 n 個(gè)元素的 std::list
容器,并將這些元素初始化為 val
。你可以通過傳遞不同的 val
值來創(chuàng)建一個(gè)包含相同值的容器。同樣,也可以傳遞一個(gè)可選的分配器參數(shù)。
std::list<int> myList(5, 42); // 創(chuàng)建一個(gè)包含 5 個(gè)元素,每個(gè)元素都是 42 的 std::list 容器
3.range (3)
這個(gè)構(gòu)造函數(shù)使用迭代器范圍 [first, last)
中的元素創(chuàng)建一個(gè) std::list
容器。這使你可以通過一個(gè)迭代器范圍來初始化容器。同樣,它也接受一個(gè)可選的分配器參數(shù)。
std::vector<int> vec = {1, 2, 3, 4, 5};
std::list<int> myList(vec.begin(), vec.end()); // 從迭代器范圍內(nèi)的元素創(chuàng)建 std::list 容器
4. copy (4)
這個(gè)構(gòu)造函數(shù)用于創(chuàng)建一個(gè)與已存在的 std::list
容器 x
相同的副本。它會(huì)將 x
中的所有元素拷貝到新的容器中。這是一個(gè)拷貝構(gòu)造函數(shù)。
std::list<int> originalList = {1, 2, 3, 4, 5};
std::list<int> copiedList(originalList); // 創(chuàng)建一個(gè)原容器的副本
這些構(gòu)造函數(shù)提供了不同的初始化方式,以便根據(jù)具體需求來創(chuàng)建 std::list 容器。根據(jù)你的數(shù)據(jù)源和其他條件,選擇適合的構(gòu)造函數(shù)來創(chuàng)建容器對(duì)象。
list迭代器(Iterators)
1. begin()
iterator begin() noexcept;
這個(gè)版本的 begin()
返回一個(gè)迭代器,可以用于修改容器內(nèi)的元素。noexcept
表示這個(gè)函數(shù)不會(huì)拋出異常。
std::list<int> myList = {1, 2, 3, 4, 5};
std::list<int>::iterator it = myList.begin(); // 獲取可修改元素的迭代器
*it = 10; // 修改第一個(gè)元素的值為 10
const_iterator begin() const noexcept;
這個(gè)版本的 begin()
返回一個(gè)只讀的迭代器,用于在不修改容器的情況下訪問元素。const
表示這個(gè)函數(shù)不會(huì)修改容器。
const std::list<int> myList = {1, 2, 3, 4, 5};
std::list<int>::const_iterator cit = myList.begin(); // 獲取只讀元素的迭代器
int firstElement = *cit; // 讀取第一個(gè)元素的值
2. end()
iterator end() noexcept;
這個(gè)版本的 end()
返回一個(gè)迭代器,可以用于修改容器內(nèi)的元素。noexcept
表示這個(gè)函數(shù)不會(huì)拋出異常。這個(gè)迭代器指向的位置實(shí)際上是容器的末尾位置之后一個(gè)虛擬的位置,所以它并不指向容器內(nèi)的任何元素。
std::list<int> myList = {1, 2, 3, 4, 5};
std::list<int>::iterator it = myList.end(); // 獲取可修改元素的迭代器
--it; // 將迭代器前移一個(gè)位置,指向最后一個(gè)元素
*it = 20; // 修改最后一個(gè)元素的值為 20
const_iterator end() const noexcept;
這個(gè)版本的 end()
返回一個(gè)只讀的迭代器,用于在不修改容器的情況下訪問元素。const
表示這個(gè)函數(shù)不會(huì)修改容器。同樣,這個(gè)迭代器也指向虛擬的位置,容器內(nèi)的最后一個(gè)元素之后。
const std::list<int> myList = {1, 2, 3, 4, 5};
std::list<int>::const_iterator cit = myList.end(); // 獲取只讀元素的迭代器
--cit; // 將迭代器前移一個(gè)位置,指向最后一個(gè)元素
int lastElement = *cit; // 讀取最后一個(gè)元素的值
3. rbegin()
reverse_iterator rbegin() noexcept;
這個(gè)版本的 rbegin()
返回一個(gè)反向迭代器,可以用于修改容器內(nèi)的元素。noexcept
表示這個(gè)函數(shù)不會(huì)拋出異常。這個(gè)反向迭代器指向容器內(nèi)的最后一個(gè)元素,可以通過遞減操作符 --
往前遍歷容器。
std::list<int> myList = {1, 2, 3, 4, 5};
std::list<int>::reverse_iterator rit = myList.rbegin(); // 獲取可修改元素的反向迭代器
*rit = 10; // 修改最后一個(gè)元素的值為 10
++rit; // 將反向迭代器往前移動(dòng)一個(gè)位置,指向倒數(shù)第二個(gè)元素
const_reverse_iterator rbegin() const noexcept;
這個(gè)版本的 rbegin()
返回一個(gè)只讀的反向迭代器,用于在不修改容器的情況下訪問元素。const
表示這個(gè)函數(shù)不會(huì)修改容器。這個(gè)反向迭代器同樣指向最后一個(gè)元素,可以通過遞減操作符 --
往前遍歷容器。
const std::list<int> myList = {1, 2, 3, 4, 5};
std::list<int>::const_reverse_iterator crit = myList.rbegin(); // 獲取只讀元素的反向迭代器
int lastElement = *crit; // 讀取最后一個(gè)元素的值
++crit; // 將反向迭代器往前移動(dòng)一個(gè)位置,指向倒數(shù)第二個(gè)元素
4. rend()
reverse_iterator rend() nothrow;
這個(gè)版本的 rend()
返回一個(gè)反向迭代器,可以用于修改容器內(nèi)的元素。nothrow
表示這個(gè)函數(shù)不會(huì)拋出異常。這個(gè)反向迭代器指向容器內(nèi)的位置,位于第一個(gè)元素之前,可以通過遞減操作符 --
往前遍歷容器。
std::list<int> myList = {1, 2, 3, 4, 5};
std::list<int>::reverse_iterator rit = myList.rend(); // 獲取可修改元素的反向迭代器
--rit; // 將反向迭代器往前移動(dòng)一個(gè)位置,指向最后一個(gè)元素
*rit = 10; // 修改最后一個(gè)元素的值為 10
const_reverse_iterator rend() const nothrow;
這個(gè)版本的 rend()
返回一個(gè)只讀的反向迭代器,用于在不修改容器的情況下訪問元素。const
表示這個(gè)函數(shù)不會(huì)修改容器。這個(gè)反向迭代器同樣指向容器的位置,位于第一個(gè)元素之前,可以通過遞減操作符 – 往前遍歷容器。
const std::list<int> myList = {1, 2, 3, 4, 5};
std::list<int>::const_reverse_iterator crit = myList.rend(); // 獲取只讀元素的反向迭代器
--crit; // 將反向迭代器往前移動(dòng)一個(gè)位置,指向最后一個(gè)元素
int lastElement = *crit; // 讀取最后一個(gè)元素的值
5. cbegin()、cend()、crbegin()、crend()
const_iterator cbegin() const noexcept;
這個(gè)成員函數(shù)返回一個(gè)指向容器元素的常量迭代器,指向容器的起始位置。通過常量迭代器,你可以遍歷容器的元素,但不能修改它們。
const_iterator cend() const noexcept;
這個(gè)成員函數(shù)返回一個(gè)指向容器元素的常量迭代器,指向容器的結(jié)束位置。這個(gè)迭代器表示一個(gè)超過容器尾部的位置,通常用于迭代器循環(huán)的終止條件。
std::list<int> myList = {1, 2, 3, 4, 5};
std::list<int>::const_iterator cit = myList.cbegin(); // 獲取常量迭代器
for (; cit != myList.cend(); ++cit) {
std::cout << *cit << " "; // 輸出容器中的元素,不修改它們
}
const_reverse_iterator crbegin() const noexcept;
這個(gè)成員函數(shù)返回一個(gè)指向容器元素的常量反向迭代器,指向容器的反向起始位置。通過常量反向迭代器,你可以反向遍歷容器的元素,但不能修改它們。
const_reverse_iterator crend() const noexcept;
這個(gè)成員函數(shù)返回一個(gè)指向容器元素的常量反向迭代器,指向容器的反向結(jié)束位置。這個(gè)迭代器表示一個(gè)超過容器首部的位置,通常用于反向迭代器循環(huán)的終止條件。
std::list<int> myList = {1, 2, 3, 4, 5};
std::list<int>::const_reverse_iterator crit = myList.crbegin(); // 獲取常量反向迭代器
for (; crit != myList.crend(); ++crit) {
std::cout << *crit << " "; // 反向輸出容器中的元素,不修改它們
}
list容量函數(shù)(Capacity)和元素訪問函數(shù)(Element access)
1. empty()
empty()
是 std::list
容器的一個(gè)成員函數(shù),用于判斷容器是否為空。它返回一個(gè)布爾值,表示容器是否不包含任何元素。函數(shù)聲明如下:
bool empty() const noexcept;
返回值:如果容器為空,則返回 true,否則返回 false。
使用示例:
#include <iostream>
#include <list>
int main() {
std::list<int> myList;
if (myList.empty()) {
std::cout << "The list is empty." << std::endl;
} else {
std::cout << "The list is not empty." << std::endl;
}
myList.push_back(42);
if (myList.empty()) {
std::cout << "The list is empty." << std::endl;
} else {
std::cout << "The list is not empty." << std::endl;
}
return 0;
}
在上面的示例中,首先創(chuàng)建一個(gè)空的 std::list
容器 myList
,然后使用 empty()
函數(shù)檢查容器是否為空,并輸出相應(yīng)的信息。然后,通過 push_back
向容器中添加一個(gè)元素,并再次使用 empty()
函數(shù)檢查容器是否為空,輸出相應(yīng)的信息。
2. size()
size()
是 std::list
容器的一個(gè)成員函數(shù),用于返回容器中元素的數(shù)量。它返回一個(gè)無符號(hào)整數(shù)類型,表示容器中的元素?cái)?shù)量。函數(shù)聲明如下:
size_type size() const noexcept;
返回值:返回容器中元素的數(shù)量,即大小。
使用示例:
#include <iostream>
#include <list>
int main() {
std::list<int> myList;
myList.push_back(1);
myList.push_back(2);
myList.push_back(3);
std::cout << "Size of the list: " << myList.size() << std::endl;
return 0;
}
在上面的示例中,我們首先創(chuàng)建一個(gè) std::list
容器 myList
,然后使用 push_back
函數(shù)向容器中添加三個(gè)元素。然后使用 size()
函數(shù)獲取容器的大小,并輸出到標(biāo)準(zhǔn)輸出。
3. max_size()
max_size()
是 std::list
容器的一個(gè)成員函數(shù),用于返回容器可能容納的最大元素?cái)?shù)量,通常受到系統(tǒng)內(nèi)存限制的影響。它返回一個(gè)無符號(hào)整數(shù)類型,表示容器的最大大小。函數(shù)簽名如下:
size_type max_size() const noexcept;
返回值:返回容器可能容納的最大元素?cái)?shù)量。
使用示例:
#include <iostream>
#include <list>
int main() {
std::list<int> myList;
std::cout << "Max size of the list: " << myList.max_size() << std::endl;
return 0;
}
在上面的示例中,我們創(chuàng)建了一個(gè)空的 std::list
容器 myList
,然后使用 max_size()
函數(shù)獲取容器的最大大小,并輸出到標(biāo)準(zhǔn)輸出。請(qǐng)注意,實(shí)際可用的最大大小取決于系統(tǒng)內(nèi)存和其他資源的限制。
4. front()
front()
是 std::list
容器的成員函數(shù),用于返回容器中第一個(gè)元素的引用。這個(gè)函數(shù)有兩個(gè)版本,一個(gè)用于可修改容器的對(duì)象,另一個(gè)用于只讀(const)容器的對(duì)象。函數(shù)的簽名如下:
reference front();
const_reference front() const;
reference:返回一個(gè)對(duì)容器中第一個(gè)元素的非常引用。
const_reference:只有在 const
容器對(duì)象上調(diào)用時(shí),才返回一個(gè)對(duì)容器中第一個(gè)元素的常引用。
使用示例:
#include <iostream>
#include <list>
int main() {
std::list<int> myList = {10, 20, 30};
int& firstElement = myList.front();
const int& constFirstElement = myList.front();
std::cout << "First element: " << firstElement << std::endl;
std::cout << "Const first element: " << constFirstElement << std::endl;
return 0;
}
在上面的示例中,我們創(chuàng)建了一個(gè) std::list
容器 myList
,其中包含三個(gè)整數(shù)元素。我們使用 front()
函數(shù)來獲取容器中的第一個(gè)元素的引用,分別存儲(chǔ)為可修改的引用 firstElement
和只讀的常引用 constFirstElement
,然后將它們輸出到標(biāo)準(zhǔn)輸出。
5. back()
back()
是 std::list 容器的成員函數(shù),用于返回容器中最后一個(gè)元素的引用。這個(gè)函數(shù)有兩個(gè)版本,一個(gè)用于可修改容器的對(duì)象,另一個(gè)用于只讀(const)容器的對(duì)象。函數(shù)的簽名如下:
reference back();
const_reference back() const;
reference:返回一個(gè)對(duì)容器中最后一個(gè)元素的非常引用。
const_reference:只有在 const 容器對(duì)象上調(diào)用時(shí),才返回一個(gè)對(duì)容器中最后一個(gè)元素的常引用。
使用示例:
#include <iostream>
#include <list>
int main() {
std::list<int> myList = {10, 20, 30};
int& lastElement = myList.back();
const int& constLastElement = myList.back();
std::cout << "Last element: " << lastElement << std::endl;
std::cout << "Const last element: " << constLastElement << std::endl;
return 0;
}
在上面的示例中,我們創(chuàng)建了一個(gè) std::list
容器 myList
,其中包含三個(gè)整數(shù)元素。我們使用 back()
函數(shù)來獲取容器中的最后一個(gè)元素的引用,分別存儲(chǔ)為可修改的引用 lastElement
和只讀的常引用 constLastElement
,然后將它們輸出到標(biāo)準(zhǔn)輸出。
list增刪查改函數(shù)(Modifiers)
1. assign
assign
是 std::list
容器的成員函數(shù),用于將容器的內(nèi)容替換為新的元素。這個(gè)函數(shù)有三個(gè)不同版本:
使用迭代器范圍:
template <class InputIterator>
void assign (InputIterator first, InputIterator last);
這個(gè)版本接受兩個(gè)迭代器參數(shù) first
和 last
,用來指定一個(gè)范圍。它會(huì)將容器的內(nèi)容替換為范圍 [first, last)
內(nèi)的元素。
使用重復(fù)元素:
void assign (size_type n, const value_type& val);
這個(gè)版本接受一個(gè)整數(shù)參數(shù) n
,和一個(gè)值 val
。它會(huì)將容器的內(nèi)容替換為 n
個(gè)值為 val
的元素。
使用初始化列表:
void assign (initializer_list<value_type> il);
這個(gè)版本接受一個(gè)初始化列表作為參數(shù)。它會(huì)將容器的內(nèi)容替換為初始化列表中的元素。
使用示例:
#include <iostream>
#include <list>
int main() {
std::list<int> myList;
myList.assign({1, 2, 3, 4, 5}); // 使用初始化列表
std::cout << "Size after assigning with initializer list: " << myList.size() << std::endl;
myList.assign(3, 100); // 使用重復(fù)元素
std::cout << "Size after assigning with repeated elements: " << myList.size() << std::endl;
std::list<int> anotherList = {10, 20, 30, 40};
myList.assign(anotherList.begin(), anotherList.end()); // 使用迭代器范圍
std::cout << "Size after assigning with iterator range: " << myList.size() << std::endl;
return 0;
}
在上面的示例中,我們首先創(chuàng)建了一個(gè)空的 std::list
容器 myList
。然后使用不同版本的 assign
函數(shù)來分別替換容器的內(nèi)容。最后,我們輸出容器的大小以驗(yàn)證操作是否成功。
2. emplace_front
template <class... Args>
void emplace_front (Args&&... args);
emplace_front
是 std::list
容器的成員函數(shù),用于在容器的開頭插入一個(gè)新元素。它通過在指定位置直接構(gòu)造元素,避免了額外的拷貝或移動(dòng)操作。
這個(gè)函數(shù)接受可變數(shù)量的參數(shù) Args...
,這些參數(shù)會(huì)被用來構(gòu)造新元素。使用 emplace_front
可以直接在容器的開頭插入元素,而不需要先創(chuàng)建一個(gè)臨時(shí)對(duì)象然后再進(jìn)行插入操作。
使用示例:
#include <iostream>
#include <list>
struct Person {
std::string name;
int age;
Person(const std::string& n, int a) : name(n), age(a) {
std::cout << "Constructing " << name << std::endl;
}
};
int main() {
std::list<Person> personList;
personList.emplace_front("zhangsan", 25);
personList.emplace_front("lisi", 30);
personList.emplace_front("wangwu", 28);
std::cout << "Person list contents:" << std::endl;
for (const auto& person : personList) {
std::cout << "Name: " << person.name << ", Age: " << person.age << std::endl;
}
return 0;
}
在上述示例中,我們首先定義了一個(gè)名為 Person
的結(jié)構(gòu)體,它有兩個(gè)成員變量:name
和 age
。然后我們創(chuàng)建了一個(gè)空的 std::list
容器 personList
,使用 emplace_front
函數(shù)分別在容器的開頭插入了幾個(gè)新的 Person
對(duì)象,直接在插入位置進(jìn)行構(gòu)造。
注意,emplace_front
的參數(shù)被傳遞給 Person
類型的構(gòu)造函數(shù),用于構(gòu)造新的 Person
對(duì)象。這樣做避免了額外的拷貝或移動(dòng)操作,提高了效率。
3. push_front
push_front
是 std::list
容器的成員函數(shù),用于在容器的開頭插入一個(gè)新元素。
這個(gè)函數(shù)有兩個(gè)版本:
void push_front (const value_type& val);
:接受一個(gè)常量引用參數(shù),會(huì)創(chuàng)建一個(gè)新元素并將參數(shù)的值拷貝到新元素中。
void push_front (value_type&& val);
:接受一個(gè)右值引用參數(shù),用于移動(dòng)構(gòu)造一個(gè)新元素。這樣可以避免額外的拷貝操作,提高了效率。
使用示例:
#include <iostream>
#include <list>
int main() {
std::list<int> myList;
int value = 20;
myList.push_front(value); // Copy insert
std::cout << "List contents:" << std::endl;
for (const auto& num : myList) {
std::cout << num << " ";
}
std::cout << std::endl;
myList.push_front(25); // Move insert
std::cout << "List contents after move insert:" << std::endl;
for (const auto& num : myList) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在上述示例中,我們首先創(chuàng)建一個(gè)空的 std::list
容器 myList
,然后使用 push_front
函數(shù)分別進(jìn)行了常量引用拷貝插入和右值引用移動(dòng)插入操作??梢钥吹剑抑狄冒姹镜?push_front
更加高效,因?yàn)樗苊饬祟~外的拷貝操作。
4. pop_front
void pop_front();
是用于從 std::list 的開頭移除一個(gè)元素的成員函數(shù)。它會(huì)刪除列表中的第一個(gè)元素,并且將列表的大小減小一個(gè)單位。
示例用法:
std::list<int> myList = {1, 2, 3, 4, 5};
myList.pop_front(); // 移除第一個(gè)元素
在上面的例子中,pop_front()
將會(huì)移除 1 這個(gè)元素,使得列表變?yōu)?{2, 3, 4, 5}。
5. emplace_back
template <class... Args> void emplace_back (Args&&... args);
是一個(gè)用于在 std::list
的末尾插入新元素的函數(shù)。它允許你通過傳遞構(gòu)造元素所需的參數(shù)來直接在列表的末尾構(gòu)造元素,避免了額外的拷貝或移動(dòng)操作。
示例用法:
std::list<std::string> myList;
myList.emplace_back("Hello");
myList.emplace_back("World");
在上面的例子中,emplace_back
函數(shù)直接在列表的末尾構(gòu)造了兩個(gè)字符串元素,分別是 "Hello"
和 "World"
。
這個(gè)函數(shù)對(duì)于避免額外的元素構(gòu)造和拷貝操作很有用,特別是在容器中存儲(chǔ)大型對(duì)象時(shí),可以提高性能。
6. push_back
void push_back (const value_type& val);
是 std::list
容器的成員函數(shù),用于在列表的末尾插入一個(gè)新元素。它接受一個(gè)常量引用作為參數(shù),將傳入的值插入到列表末尾。
示例用法:
std::list<int> myList;
myList.push_back(10);
myList.push_back(20);
myList.push_back(30);
在上面的例子中,push_back
函數(shù)分別將整數(shù) 10、20
和 30
插入到列表的末尾。
這個(gè)函數(shù)在操作上相對(duì)簡單,但是可能涉及到內(nèi)存分配和元素拷貝操作。如果插入的元素比較大,可能會(huì)導(dǎo)致額外的性能開銷。
7. pop_back
void pop_back();
是 std::list
容器的成員函數(shù),用于刪除列表中的最后一個(gè)元素。它會(huì)將列表的最后一個(gè)元素從容器中移除,同時(shí)釋放相應(yīng)的內(nèi)存資源。
示例用法:
std::list<int> myList;
myList.push_back(10);
myList.push_back(20);
myList.push_back(30);
myList.pop_back();
在上面的例子中,pop_back
函數(shù)會(huì)移除列表中的元素 30
,使列表變?yōu)?[10, 20]
。
需要注意的是,調(diào)用 pop_back
函數(shù)前需要確保列表不為空,否則會(huì)出現(xiàn)未定義的行為??梢酝ㄟ^ empty()
函數(shù)來判斷列表是否為空。
8. emplace
template <class... Args> iterator emplace (const_iterator position, Args&&... args);
是 std::list
容器的成員函數(shù),用于在指定位置插入一個(gè)新元素,并將元素構(gòu)造函數(shù)的參數(shù)傳遞給插入的元素。
參數(shù)說明:
position
:要插入新元素的位置的迭代器。args
:傳遞給新元素構(gòu)造函數(shù)的參數(shù)。
該函數(shù)返回一個(gè)迭代器,指向新插入的元素。
示例用法:
std::list<int> myList = {10, 20, 30};
auto it = myList.begin();
++it; // 移動(dòng)到第二個(gè)元素的位置
myList.emplace(it, 25); // 在第二個(gè)元素位置插入值為 25 的元素
在上面的例子中,emplace
函數(shù)在第二個(gè)元素的位置插入了一個(gè)值為 25
的新元素,使列表變?yōu)?[10, 25, 20, 30]
。返回的迭代器指向插入的元素 25
。
這個(gè)函數(shù)適用于在任意位置插入元素,并且可以通過參數(shù)直接傳遞給元素的構(gòu)造函數(shù)。
9. insert
iterator insert (iterator position, const value_type& val);
void insert (iterator position, size_type n, const value_type& val);
template <class InputIterator>
void insert (iterator position, InputIterator first, InputIterator last);
iterator insert (iterator position, const value_type& val);
是 std::list
容器的成員函數(shù),用于在指定位置插入一個(gè)新元素,新元素的值由 val
參數(shù)確定。
參數(shù)說明:
position
:要插入新元素的位置的迭代器。val
:要插入的元素的值。
該函數(shù)返回一個(gè)迭代器,指向插入的元素。
示例用法:
std::list<int> myList = {10, 20, 30};
auto it = myList.begin();
++it; // 移動(dòng)到第二個(gè)元素的位置
myList.insert(it, 25); // 在第二個(gè)元素位置插入值為 25 的元素
void insert (iterator position, size_type n, const value_type& val);
是另一個(gè)版本的插入函數(shù),可以插入指定數(shù)量的相同值的元素。
參數(shù)說明:
position
:要插入新元素的位置的迭代器。n
:要插入的相同元素的數(shù)量。val
:要插入的元素的值。
template <class InputIterator> void insert (iterator position, InputIterator first, InputIterator last);
是另一個(gè)版本的插入函數(shù),可以從指定范圍的迭代器中插入一系列元素。
參數(shù)說明:
position
:要插入新元素的位置的迭代器。first
和 last
:要插入的元素范圍的迭代器。
這些 insert
函數(shù)提供了不同的插入方式,使你可以根據(jù)需要靈活地向列表中添加元素。
10. erase
iterator erase (iterator position);
和 iterator erase (iterator first, iterator last);
是 std::list
容器的成員函數(shù),用于從列表中刪除一個(gè)或多個(gè)元素。
iterator erase (iterator position);
刪除指定位置的元素,并返回指向下一個(gè)元素的迭代器。
參數(shù)說明:
position
:要?jiǎng)h除的元素的位置的迭代器。
返回值:指向被刪除元素之后的元素的迭代器。
示例用法:
std::list<int> myList = {10, 20, 30, 40};
auto it = myList.begin();
++it; // 移動(dòng)到第二個(gè)元素的位置
myList.erase(it); // 刪除第二個(gè)元素
iterator erase (iterator first, iterator last);
刪除指定范圍內(nèi)的元素,并返回指向被刪除范圍之后的元素的迭代器。
參數(shù)說明:
first
和 last
:要?jiǎng)h除的元素范圍的迭代器,刪除的范圍包括 first,但不包括 last。
返回值:指向被刪除范圍之后的元素的迭代器。
示例用法:
std::list<int> myList = {10, 20, 30, 40};
auto it1 = myList.begin();
auto it2 = myList.begin();
std::advance(it2, 2); // 移動(dòng)到第三個(gè)元素的位置
myList.erase(it1, it2); // 刪除第一個(gè)和第二個(gè)元素
這些函數(shù)允許你根據(jù)需要從列表中刪除一個(gè)或多個(gè)元素,并返回正確的迭代器以便進(jìn)行后續(xù)操作。
11. swap
void swap(list& x);
是 std::list
容器的成員函數(shù),用于交換當(dāng)前列表與另一個(gè)列表 x
的內(nèi)容。
參數(shù)說明:
x
:要與當(dāng)前列表進(jìn)行內(nèi)容交換的另一個(gè)列表。
示例用法:
#include <iostream>
#include <list>
int main() {
std::list<int> myList1 = {1, 2, 3};
std::list<int> myList2 = {4, 5, 6};
myList1.swap(myList2); // 交換兩個(gè)列表的內(nèi)容
std::cout << "myList1: ";
for (int num : myList1) {
std::cout << num << " ";
}
std::cout << std::endl;
std::cout << "myList2: ";
for (int num : myList2) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在上述示例中,myList1
和 myList2
的內(nèi)容被交換,導(dǎo)致輸出中顯示的內(nèi)容分別為 4 5 6
和 1 2 3
。這個(gè)函數(shù)對(duì)于在不同列表之間交換內(nèi)容非常有用。
12. resize
void resize(size_type n, value_type val = value_type());
是 std::list
容器的成員函數(shù),用于調(diào)整列表的大小。
參數(shù)說明:
n
:指定調(diào)整后的大小。val
:在列表擴(kuò)展時(shí),用于填充新元素的值。默認(rèn)值為 value_type()
,即類型的默認(rèn)構(gòu)造函數(shù)創(chuàng)建的值。
該函數(shù)通過在列表的末尾添加或刪除元素,使列表的大小調(diào)整為指定的大小 n
。如果新的大小大于當(dāng)前大小,新元素將用指定的值 val
填充。如果新的大小小于當(dāng)前大小,多余的元素將被刪除。
示例用法:
#include <iostream>
#include <list>
int main() {
std::list<int> myList = {1, 2, 3, 4, 5};
myList.resize(3); // 調(diào)整列表大小為3
std::cout << "myList after resize to 3: ";
for (int num : myList) {
std::cout << num << " ";
}
std::cout << std::endl;
myList.resize(5, 0); // 調(diào)整列表大小為5,并用0填充新元素
std::cout << "myList after resize to 5 with filling 0: ";
for (int num : myList) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在上述示例中,首先調(diào)用 resize(3)
后,列表中只有前3個(gè)元素保留,然后調(diào)用 resize(5, 0)
后,列表中總共有5
個(gè)元素,其中新添加的2
個(gè)元素被填充為0
。
13. clear
void clear();
是 std::list
容器的成員函數(shù),用于清空列表中的所有元素,使列表變?yōu)榭樟斜怼?/p>
該函數(shù)會(huì)刪除列表中的所有元素,使列表變?yōu)榭?,但并不?huì)釋放列表所占用的內(nèi)存空間,所以列表的容量不會(huì)變化。這可以有效地回收元素所占用的資源,但保留容量可以減少頻繁的內(nèi)存分配和釋放操作,以提高性能。
示例用法:
#include <iostream>
#include <list>
int main() {
std::list<int> myList = {1, 2, 3, 4, 5};
std::cout << "myList before clear: ";
for (int num : myList) {
std::cout << num << " ";
}
std::cout << std::endl;
myList.clear(); // 清空列表
std::cout << "myList after clear: ";
for (int num : myList) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在上述示例中,首先輸出了清空前的列表元素,然后調(diào)用 clear()
后,列表中的所有元素被刪除,輸出了清空后的列表元素,此時(shí)列表為空。
list操作函數(shù)(Operations)
1. splice
void splice (iterator position, list& x);
該成員函數(shù)用于將另一個(gè)列表 x
中的所有元素移動(dòng)到當(dāng)前列表中,插入到指定位置 position
前。x
列表在移動(dòng)后會(huì)變?yōu)榭樟斜怼?/p>
示例用法:
#include <iostream>
#include <list>
int main() {
std::list<int> myList1 = {1, 2, 3};
std::list<int> myList2 = {4, 5, 6};
auto it = myList1.begin();
std::advance(it, 2);
myList1.splice(it, myList2); // 將 myList2 的元素插入到 myList1 中
std::cout << "myList1 after splice: ";
for (int num : myList1) {
std::cout << num << " ";
}
std::cout << std::endl;
std::cout << "myList2 after splice: ";
for (int num : myList2) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
void splice (iterator position, list& x, iterator i);
該成員函數(shù)用于將另一個(gè)列表 x
中的元素移動(dòng)到當(dāng)前列表中,插入到指定位置 position
前,但只移動(dòng)另一個(gè)列表 x
中的迭代器 i
指向的元素。
示例用法:
#include <iostream>
#include <list>
int main() {
std::list<int> myList1 = {1, 2, 3};
std::list<int> myList2 = {4, 5, 6};
auto it1 = myList1.begin();
std::advance(it1, 1);
auto it2 = myList2.begin();
myList1.splice(it1, myList2, it2); // 將 myList2 中的第一個(gè)元素插入到 myList1 中
std::cout << "myList1 after splice: ";
for (int num : myList1) {
std::cout << num << " ";
}
std::cout << std::endl;
std::cout << "myList2 after splice: ";
for (int num : myList2) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
void splice (iterator position, list& x, iterator first, iterator last);
該成員函數(shù)用于將另一個(gè)列表 x
中的一段元素范圍 [first, last)
移動(dòng)到當(dāng)前列表中,插入到指定位置 position
前。
示例用法:
#include <iostream>
#include <list>
int main() {
std::list<int> myList1 = {1, 2, 3};
std::list<int> myList2 = {4, 5, 6};
auto it1 = myList1.begin();
std::advance(it1, 1);
auto it2_first = myList2.begin();
auto it2_last = myList2.begin();
std::advance(it2_last, 2);
myList1.splice(it1, myList2, it2_first, it2_last); // 將 myList2 中的前兩個(gè)元素插入到 myList1 中
std::cout << "myList1 after splice: ";
for (int num : myList1) {
std::cout << num << " ";
}
std::cout << std::endl;
std::cout << "myList2 after splice: ";
for (int num : myList2) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
這些 splice
函數(shù)允許你在列表中移動(dòng)元素,從一個(gè)列表中移動(dòng)到另一個(gè)列表中,或在同一列表內(nèi)重新排列元素的位置,而不需要進(jìn)行元素的復(fù)制和刪除。
2. remove
void remove (const value_type& val);
該成員函數(shù)用于從列表中移除所有等于給定值 val
的元素。
示例用法:
#include <iostream>
#include <list>
int main() {
std::list<int> myList = {1, 2, 3, 2, 4, 2, 5};
myList.remove(2); // 移除列表中所有值為 2 的元素
std::cout << "myList after remove: ";
for (int num : myList) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在示例中,myList
列表中的值為 2
的元素被移除,最終輸出為 "1 3 4 5"
。
3. remove_if
template <class Predicate> void remove_if (Predicate pred);
這個(gè)成員函數(shù)用于根據(jù)給定的謂詞函數(shù) pred
移除滿足特定條件的元素。
謂詞函數(shù) pred
接受一個(gè)參數(shù)并返回一個(gè)布爾值,用于判斷是否需要移除該元素。如果謂詞返回 true
,則該元素將被移除。
示例用法:
#include <iostream>
#include <list>
bool isEven(int num) {
return num % 2 == 0;
}
int main() {
std::list<int> myList = {1, 2, 3, 4, 5, 6, 7, 8, 9};
myList.remove_if(isEven); // 移除列表中所有偶數(shù)
std::cout << "myList after remove_if: ";
for (int num : myList) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在示例中,myList
列表中的偶數(shù)元素被移除,最終輸出為 "1 3 5 7 9"
。函數(shù) isEven
是一個(gè)謂詞函數(shù),用于判斷是否為偶數(shù)。
4. unique
void unique();
這個(gè)成員函數(shù)用于移除列表中相鄰的重復(fù)元素。它只保留第一個(gè)出現(xiàn)的重復(fù)元素,移除后續(xù)的重復(fù)元素。
示例用法:
#include <iostream>
#include <list>
int main() {
std::list<int> myList = {1, 2, 2, 3, 4, 4, 4, 5};
myList.unique(); // 移除相鄰的重復(fù)元素
std::cout << "myList after unique: ";
for (int num : myList) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在示例中,myList
列表中的相鄰重復(fù)元素被移除,最終輸出為 "1 2 3 4 5"
。
template <class BinaryPredicate> void unique (BinaryPredicate binary_pred);
這個(gè)成員函數(shù)在移除相鄰重復(fù)元素時(shí),使用自定義的二元謂詞函數(shù) binary_pred
來判斷是否為重復(fù)元素。該謂詞函數(shù)接受兩個(gè)參數(shù),并返回一個(gè)布爾值,用于判斷兩個(gè)元素是否相等。
示例用法:
#include <iostream>
#include <list>
bool isEqual(int a, int b) {
return a == b;
}
int main() {
std::list<int> myList = {1, 2, 2, 3, 4, 4, 4, 5};
myList.unique(isEqual); // 使用 isEqual 判斷是否為重復(fù)元素
std::cout << "myList after unique with custom predicate: ";
for (int num : myList) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在示例中,通過自定義的謂詞函數(shù) isEqual
判斷相鄰的元素是否相等,移除相鄰的重復(fù)元素,最終輸出為 "1 2 3 4 5"
。
5. merge
void merge(list& x);
這個(gè)成員函數(shù)用于將另一個(gè)列表 x
合并到當(dāng)前列表中,合并后的列表會(huì)按照升序排列。
示例用法:
#include <iostream>
#include <list>
int main() {
std::list<int> myList1 = {1, 3, 5};
std::list<int> myList2 = {2, 4, 6};
myList1.merge(myList2); // 將 myList2 合并到 myList1 中
std::cout << "myList1 after merge: ";
for (int num : myList1) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在示例中,myList2
列表被合并到了 myList1
中,合并后的列表按照升序排列,最終輸出為 "1 2 3 4 5 6"
。
template <class Compare> void merge(list& x, Compare comp);
這個(gè)成員函數(shù)與上面的 merge
函數(shù)類似,但是它允許提供一個(gè)自定義的比較函數(shù) comp 來決定合并后的順序。
示例用法:
#include <iostream>
#include <list>
bool descendingOrder(int a, int b) {
return a > b;
}
int main() {
std::list<int> myList1 = {5, 3, 1};
std::list<int> myList2 = {6, 4, 2};
myList1.merge(myList2, descendingOrder); // 使用自定義比較函數(shù)合并
std::cout << "myList1 after merge with custom comparison: ";
for (int num : myList1) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在示例中,通過自定義的比較函數(shù) descendingOrder
,將 myList2
列表合并到了 myList1
中,合并后的列表按照降序排列,最終輸出為 "6 5 4 3 2 1"
。
6. sort
void sort();
這個(gè)成員函數(shù)用于對(duì)列表進(jìn)行升序排序,默認(rèn)使用 <
運(yùn)算符進(jìn)行比較。
示例用法:
#include <iostream>
#include <list>
int main() {
std::list<int> myList = {5, 3, 1, 4, 2};
myList.sort(); // 對(duì)列表進(jìn)行升序排序
std::cout << "myList after sorting: ";
for (int num : myList) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在示例中,列表中的元素經(jīng)過排序后變?yōu)?"1 2 3 4 5"
。
template <class Compare> void sort(Compare comp);
這個(gè)成員函數(shù)與上面的 sort
函數(shù)類似,但是它允許提供一個(gè)自定義的比較函數(shù) comp
來決定排序的順序。
示例用法:
#include <iostream>
#include <list>
bool descendingOrder(int a, int b) {
return a > b;
}
int main() {
std::list<int> myList = {5, 3, 1, 4, 2};
myList.sort(descendingOrder); // 使用自定義比較函數(shù)進(jìn)行降序排序
std::cout << "myList after custom sorting: ";
for (int num : myList) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在示例中,通過自定義的比較函數(shù) descendingOrder
,列表中的元素經(jīng)過排序后變?yōu)?"5 4 3 2 1"
。
7. reverse
void reverse();
函數(shù)用于將列表中的元素逆序排列。
示例用法:
#include <iostream>
#include <list>
int main() {
std::list<int> myList = {1, 2, 3, 4, 5};
myList.reverse(); // 將列表中的元素逆序排列
std::cout << "myList after reversing: ";
for (int num : myList) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在示例中,列表中的元素經(jīng)過逆序排列后變?yōu)?"5 4 3 2 1"
。
list的迭代器失效
迭代器失效即迭代器所指向的節(jié)點(diǎn)的無效,即該節(jié)點(diǎn)被刪除了。因?yàn)閘ist的底層結(jié)構(gòu)為帶頭結(jié)點(diǎn)的雙向循環(huán)鏈表,因此在list中進(jìn)行插入時(shí)是不會(huì)導(dǎo)致list的迭代器失效的,只有在刪除時(shí)才會(huì)失效,并且失效的只是指向被刪除節(jié)點(diǎn)的迭代器,其他迭代器不會(huì)受到影響。
當(dāng)使用 std::list
進(jìn)行刪除操作時(shí),可能會(huì)導(dǎo)致迭代器失效。下面是一個(gè)示例:
#include <iostream>
#include <list>
int main() {
std::list<int> myList = {1, 2, 3, 4, 5};
auto it = myList.begin();
++it; // Move the iterator to the second element
myList.erase(it); // Erase the second element
for (auto num : myList) {
std::cout << num << " ";
}
return 0;
}
在上面的示例中,當(dāng)我們在第二個(gè)元素位置處使用 erase
函數(shù)刪除元素后,迭代器 it
就會(huì)失效,因?yàn)樗赶虻脑匾呀?jīng)被刪除。如果我們嘗試使用失效的迭代器,可能會(huì)導(dǎo)致未定義的行為。
要修正這個(gè)問題,可以使用 erase
函數(shù)的返回值,它會(huì)返回一個(gè)指向下一個(gè)有效元素的迭代器:
#include <iostream>
#include <list>
int main() {
std::list<int> myList = {1, 2, 3, 4, 5};
auto it = myList.begin();
++it; // Move the iterator to the second element
it = myList.erase(it); // Erase the second element and update the iterator
for (auto num : myList) {
std::cout << num << " ";
}
return 0;
}
在這個(gè)修正后的示例中,我們使用 erase
函數(shù)的返回值更新了迭代器 it
,以確保它指向的是有效的元素。這樣就避免了使用失效迭代器引發(fā)的問題。文章來源:http://www.zghlxwxcb.cn/news/detail-647915.html
結(jié)語
有興趣的小伙伴可以關(guān)注作者,如果覺得內(nèi)容不錯(cuò),請(qǐng)給個(gè)一鍵三連吧,蟹蟹你喲!??!
制作不易,如有不正之處敬請(qǐng)指出
感謝大家的來訪,UU們的觀看是我堅(jiān)持下去的動(dòng)力
在時(shí)間的催化劑下,讓我們彼此都成為更優(yōu)秀的人吧?。?!文章來源地址http://www.zghlxwxcb.cn/news/detail-647915.html
到了這里,關(guān)于C++初階之一篇文章教會(huì)你list(理解和使用)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!