顺序容器操作: 添加元素
2023年12月22日 2023年12月23日
顺序容器 | 添加元素 | 扩容 |
---|---|---|
array | X | - |
vector(string) | O | 有可能 |
deque | O | 有可能 |
list | O | - |
forward_list | O | - |
会改变容器大小
不一定需要扩容
容器对添加元素操作的支持
顺序容器 | 插入尾元素: push_back/emplace_back | 插入首元素: push_front/emplace_front | 指定位置插入元素: insert/emplace |
---|---|---|---|
vector(string) | O | X | O; 移动元素会产生开销 |
deque | O | O | O; 移动元素会产生开销 |
list | O | O | O |
forward_list | X | O; 可以通过首前迭代器完成 | -; forward_list的insert和emplace是定制的 |
示例
1c.push_back(t); 2 3c.push_front(t);
1c.emplace_back(args); 2 3c.emplace_front(args); 4 5c.emplace(p, args);
1c.insert(p, t); 2 3c.insert(p, n, t); 4 5c.insert(p, b, e); 6 7c.insert(p, il);
区分添加元素操作
操作 | 使用参数构造新元素 | 新元素为给定元素的拷贝 | 支持插入单个元素 | 支持插入多个元素 | 支持任意指定位置插入元素 | 只支持首/尾插入元素 |
---|---|---|---|---|---|---|
push_back/push_front | - | O | O | - | - | O |
emplace_back/emplace_front | O | - | O | - | - | O |
emplace | O | - | O | - | O | - |
insert | - | O | O | O | O | - |
是否需要移动元素
顺序容器 | push_back/emplace_back | push_front/emplace_front | emplace/insert |
---|---|---|---|
vector(string) | X | - | O; 非尾加需要 |
deque | X | X | O; 非首/尾加需要 |
list | X | X | X |
forward_list | - | X | - |
push_back/push_front操作
返回void
- | |
---|---|
push_back | 插入尾元素 |
push_front | 插入首元素 |
1c.push_back(t); 2 3c.push_front(t);
push_back操作
1string word; 2 3while (cin >> word) 4 container.push_back(word); // container可以是vector,list,deque 5 6void pluralize(size_t cnt, string &word) 7{ 8 if (cnt > 1) 9 word.push_back('s'); 10}
1struct Sales_data 2{ 3 Sales_data() = default; 4 Sales_data(const string &s) : bookNo(s) {} 5 Sales_data(cosnt string &s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p*n) {} 6 Sales_data(istream &); 7 8 string isbn() const { return bookNo; } 9 Sales_data& combine(const Sales_data&); 10 double avg_price() const; 11 string bookNo; 12 unsigned units_sold = 0; 13 double revenue = 0.0; 14}; 15 16c.push_back(Sales_data("978-0590353403", 25, 15.99)); 17// 构造临时对象,拷贝到容器
push_front操作
1list<int> ilist; 2 3for (size_t ix = 0; ix != 4; ++ix) 4 ilist.push_front(ix); 5 6// ilist = {3, 2, 1, 0};
emplace_back/emplace_front/emplace操作
返回void
- emplace系列操作在容器中直接构造元素
传递给emplace系列操作的参数必须与元素类型的构造函数相匹配 - 使用emplace系列操作时,将参数传递给元素类型的构造函数,构造函数使用这些参数在容器管理的内存空间中直接构造元素
使用push或者insert系列添加元素时,这些对象被拷贝到容器中 - emplace系列操作是新标准引入的3个新成员
emplace系列操作为emplace_back/emplace_front/emplace
- | |
---|---|
emplace_back | 新构造的元素作为尾元素插入 |
emplace_front | 新构造的元素作为首元素插入 |
emplace | 在指定位置插入新构造的元素 |
1c.emplace_back(args); 2 3c.emplace_front(args); 4 5c.emplace(p, args);
emplace_back操作
在容器中构造对象
1struct Sales_data 2{ 3 Sales_data() = default; 4 Sales_data(const string &s) : bookNo(s) {} 5 Sales_data(cosnt string &s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p*n) {} 6 Sales_data(istream &); 7 8 string isbn() const { return bookNo; } 9 Sales_data& combine(const Sales_data&); 10 double avg_price() const; 11 string bookNo; 12 unsigned units_sold = 0; 13 double revenue = 0.0; 14}; 15 16// 使用默认构造函数 17c.emplace_back(); 18 19c.emplace_back("978-0590353403", 25, 15.99);
emplace_front操作
1struct Sales_data 2{ 3 Sales_data() = default; 4 Sales_data(const string &s) : bookNo(s) {} 5 Sales_data(cosnt string &s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p*n) {} 6 Sales_data(istream &); 7 8 9 string isbn() const { return bookNo; } 10 Sales_data& combine(const Sales_data&); 11 double avg_price() const; 12 string bookNo; 13 unsigned units_sold = 0; 14 double revenue = 0.0; 15}; 16 17 18// 匹配Sales_data(cosnt string &, unsigned, double) 19c.emplace_front("978-0590353403", 25, 15.99);
emplace操作
返回指向位置p的迭代器. p位置对应新添加的元素
- b和e分别为顺序容器的首迭代器和尾后迭代器
指定位置p的范围为[b, e], 刚好覆盖容器当前可增加元素的所有位置 - [p, e)位置元素后移
在p处构造新元素并插入 - 使用emplace操作,可以为vector(string)模拟emplace_front操作
forward_list支持emplace_front,有自己的emplace版本
1struct Sales_data 2{ 3 Sales_data() = default; 4 Sales_data(const string &s) : bookNo(s) {} 5 Sales_data(cosnt string &s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p*n) {} 6 Sales_data(istream &); 7 8 string isbn() const { return bookNo; } 9 Sales_data& combine(const Sales_data&); 10 double avg_price() const; 11 string bookNo; 12 unsigned units_sold = 0; 13 double revenue = 0.0; 14}; 15 16c.emplace(iter, "999-999999999");
insert操作
返回指向位置p的迭代器. p位置对应新添加的(第一个)元素
- b和e分别为顺序容器的首迭代器和尾后迭代器
指定位置p的范围为[b, e], 刚好覆盖容器当前可增加元素的所有位置 - [p, e)位置元素后移
从p处开始插入新元素 - 使用insert,可以为vector(string)模拟push_front
forward_list有自己的insert版本
提供重载版本
-
插入单个元素
1c.insert(p, t);
-
插入若干个相同元素
1c.insert(p, n, t);
-
插入多个元素,由迭代器范围给出
[b, e)
1c.insert(p, b, e);
-
插入多个元素,由列表给出
1c.insert(p, il);
n为0/[b, e)为空/il为空时,返回p
使用insert操作插入单个元素
1vector<int> ivec{0, 1, 2, 3, 5, 6, 7}; 2 auto p = ivec.begin() + 4; 3 ivec.insert(p, 4); 4 5// ivec = {0, 1, 2, 3, 4, 5, 6, 7};
为vector模拟push_front
1vector<string> svec; 2 3svec.insert(svec.begin(), "Hello!");
为list模拟push_front
1list<string> slist; 2 3slist.insert(slist.begin(), "Hello!"); 4// <=> 5// slist.push_front("Hello!");
使用insert操作插入若干个相同元素
1vector<int> ivec{0, 1, 2, 3, 7}; 2auto p = ivec.begin() + 4; 3ivec.insert(p, 3, 0); 4 5// ivec = {0, 1, 2, 3, 0, 0, 0, 7};
1vector<string> svec; 2 3svec.insert(svec.end(), 10, "Anna");
使用insert操作插入多个元素, 由迭代器范围给出
迭代器不能指向本容器
1vector<int> ivec{0, 1, 2, 3, 7}; 2vector<int> ivec2{4, 5, 6}; 3auto p = ivec.begin() + 4; 4ivec.insert(p, ivec2.begin(), ivec2.end()); 5 6// ivec = {0, 1, 2, 3, 4, 5, 6, 7};
1vector<string> v = {"quasi", "simba", "frollo", "scar"}; 2list<string> slist; 3 4slist.insert(slist.begin(), v.end() - 2, v.end()); 5// slist = {"frollo", "scar"}; 6 7slist.insert(slist.end(), {"these", "words", "will", "go", "at", "the", "end"}); 8// slist = {"frollo", "scar", "these", "words", "will", "go", "at", "the", "end"};
使用insert操作插入多个元素, 由列表给出
1vector<int> ivec{0, 1, 2, 3, 7}; 2auto p = ivec.begin() + 4; 3ivec.insert(p, {4, 5, 6}); 4 5// ivec = {0, 1, 2, 3, 4, 5, 6, 7};
使用insert的返回值
模拟push_front
1list<string> lst; 2 3auto iter = lst.begin(); 4// <=> 5// auto iter = lst.end(); 6// 列表为空时,begin和end的返回值一样 7 8string word; 9while (cin >> word) 10 iter = lst.insert(iter, word); // 每回都插入作为首元素 11 12// <=> 13// lst.push_front(word); 14// 返回的是首元素的位置