标准库中的顺序容器包括:
(1)、vector:可变大小数组。支持快速随机访问。在尾部之外的位置插入或删除元素可能很慢。
(2)、deque:双端队列。支持快速随机访问。在头尾位置插入/删除速度很快。
(3)、list:双向链表。只支持双向顺序访问。在list中任何位置进行插入/删除操作速度都很快。
(4)、forward_list:单向链表。只支持单向顺序访问。在链表任何位置进行插入/删除操作速度都很快。
(5)、array:固定大小数组。支持快速随机访问。不能添加或删除元素。
(6)、string:与vector相似的容器,但专门用于保存字符。随机访问快。在尾部插入/删除速度快。
除了固定大小的array外,其它容器都提供高效、灵活的内存管理。我们可以添加和删除元素,扩张和收缩容器的大小。容器保存元素的策略对容器操作的效率有着固定的,有时是重大的影响。在某些情况下,存储策略还会影响特定容器是否支持特定操作。
std::array
std::array是在C++11中才引入的,与内置数组相比,array是一种更安全、更容易使用的数组类型。与内置数组类似,array对象的大小是固定的。因此,array不支持添加和删除元素以及改变容器大小的操作。与内置数组一样,标准库array的大小也是类型的一部分。当定义一个array时,除了指定元素类型,还要指定容器大小。为了使用array类型,我们必须同时指定元素类型和大小。array仅仅是为普通数组添加了一些成员或全局函数,这使得数组能够被当成标准容器来使用。array不能被动态地扩展或压缩。
template<
class T,
std::size_t N
> struct array;
std::array<int,3> a={1,2,3};
// construction uses aggregate initialization
//这里要添加双括号
std::array<int, 3> a1{ {1, 2, 3} }; // double-braces required in C++11 prior to
// the CWG 1270 revision (not needed in C++11
// after the revision and in C++14 and beyond)
//如果添加=号,则不用双括号了
std::array<int, 3> a2 = {1, 2, 3}; // double braces never required after =
std::array<std::string, 2> a3 = { std::string("a"), "b" };
//定义二维数组同理,不够的补0
std::array<std::array<int,3>,3> b={1,2,3,4,5,6,7,8,9};
std::sort(b.begin(),b.end());
//有一个拷贝是倒序拷贝
std::array<int,9> m={1,2,3,4,5,6,7,8,9};
std::array<int,9> n;
std::reverse_copy(std::begin(b),std::end(b),std::begin(n));
//注意begin和end都是一样的
std::reverse_copy(b.begin(), b.end(), std::begin(a));
//如果单纯的将一个容器倒序,可以使用,如下
std::reverse(b.begin(),b.end());
//将两个数据交换位置
auto it1 = b.begin();
std::advance(it1, 3);
auto it2 = b.begin();
std::iter_swap(it1, it2);
std::vector
Inserts elements at the specified location in the container.
insert()
std::vector<int> vect = {11, 2, 31, 4, 5, 61, 7, 85};
auto it = std::begin(vect);
vect.insert(it, 66);
结果:66 11, 2, 31, 4, 5, 61, 7, 85
vect.insert(it,3, 66);
结果:66 66 66 11, 2, 31, 4, 5, 61, 7, 85
关于vector的push_back和emplace_back两者区别
后者效率高一些,从官方代码可以看到:
#include <iostream>
#include <string>
#include <vector>
struct A {
std::string s;
A(std::string str) : s(std::move(str)) { std::cout << " constructed\n"; }
A(const A& o) : s(o.s) { std::cout << " copy constructed\n"; }
A(A&& o) : s(std::move(o.s)) { std::cout << " move constructed\n"; }
A& operator=(const A& other) {
s = other.s;
std::cout << " copy assigned\n";
return *this;
}
A& operator=(A&& other) {
s = std::move(other.s);
std::cout << " move assigned\n";
return *this;
}
};
int main()
{
std::vector<A> container;
// reserve enough place so vector does not have to resize
container.reserve(10);
std::cout << "construct 2 times A:\n";
A two { "two" };
A three { "three" };
std::cout << "emplace:\n";
//直接在这里就地构造一个,而不用拷贝构造了
container.emplace(container.end(), "one");
std::cout << "emplace with A&:\n";
container.emplace(container.end(), two);
std::cout << "emplace with A&&:\n";
container.emplace(container.end(), std::move(three));
std::cout << "content:\n";
for (const auto& obj : container)
std::cout << ' ' << obj.s;
std::cout << '\n';
}
这里注意一点就是end()这个迭代器什么也不包含,比如:
std::array<int, 10> b = {11, 2, 31, 4, 5, 61, 7, 85}
auto it1 = b.begin();
std::advance(it1, 3);
auto it2 = b.end();
//这里必须要首先--然后才指向最后一个元素
std::iter_swap(it1, --it2);
std::list
assign()
-
Replaces the contents with count copies of value value
void assign( size_type count, const T& value ); -
Replaces the contents with copies of those in the range [first, last). The behavior is undefined if either argument is an iterator into *this.
template< class InputIt >
void assign( InputIt first, InputIt last ); -
Replaces the contents with the elements from the initializer list ilist.
void assign( std::initializer_list ilist ); c++11
std::array<int, 10> b = {11, 2, 31, 4, 5, 61, 7, 85};
std::list<int> list = {11, 2, 31, 4, 5, 61, 7, 85};
list.assign({
1,
8,
9,
});
list.assign(9, 0);
list.assign(b.begin(), b.end());
std::map
函数
at()
operator[]()
std::map<std::string, int> myMap{{"gpu", 1}, {"cpu", 2}, {"ssd", 3}};
auto n = myMap["ssd"];
auto m = myMap.at("ssd");
insert()
Inserts element(s) into the container, if the container doesn’t already contain an element with an equivalent key.
myMap.insert(std::make_pair("ffd", 6));
myMap.insert({"xyz", 8});
std::priority_queue
const auto re = {1, 8, 6, 3, 4, 0, 1, 7};
std::priority_queue<int, std::vector<int>, std::less<int>> q;
for (int n : re)
q.push(n);
print_queue(q);
结果:8 7 6 4 3 1 1 0