C++ 标准库中的内容比我们有时间讨论的要多得多。我们将只关注一些我们还没有探索过的最常用的特性。
迭代器的作用与 IEnumerable 和中的相关接口相同。NET,例如提供一种在集合中导航的通用方法。例如,给定一个std::vector
,您可以使用以下代码循环遍历它的项目集合:
vector<int> vec;
vec.push_back(1);
vec.push_back(4);
vec.push_back(7);
vec.push_back(12);
vec.push_back(8);
for (auto i = begin(vec); i != end(vec); i++)
{
wcout << *i << endl;
}
std::begin
函数提供了一个指向集合第一项的迭代器。std::end
提供一个迭代器,表示我们已经到达集合的末尾;集合的最后一个项目,假设集合中有任何项目,是std::end
给我们的项目之前的一个项目。这就是为什么我们在for
循环中检查!=
。如果集合中没有项目,则std::begin
和std::end
将返回相同的值。
除了这两个模板函数的迭代器之外,许多集合还通过名为cbegin
和cend
的成员函数提供const
迭代器,通过rbegin
和rend
提供反向迭代器(反向循环遍历集合),通过crbegin
和crend
提供const
反向迭代器。在前面的例子中,你可以用vec.rbegin()
替换begin(vec)
,用vec.rend()
替换end(vec)
,反向遍历向量。
C++ 11 增加了一种额外类型的for
循环,称为基于范围的for
循环,它提供的功能类似于 C# 中的foreach
循环。基于范围的for
循环使用迭代器,省去了去引用指针的麻烦,也省去了错误检查结束的可能性。基于范围的for
循环相当于前面示例中的for
循环,如下所示:
for (auto item : vec)
{
wcout << item << endl;
}
你最有可能使用的收藏是std::vector
。它是一个快速的通用集合,类似于. NET 中的List<T>
,可以在<vector>
头文件中找到。
要在向量末尾添加一个项目,使用成员函数push_back
。要从向量末尾移除一个项目,请使用pop_back
。您可以像访问数组一样,使用[]
访问索引处的项目。要在特定的从零开始的索引处添加元素或元素范围,请使用insert
成员函数。要删除特定从零开始的索引处的元素或元素范围,请使用erase
成员函数。
C++ 11 中增加的一个简洁特性是emplace
和emplace_back
成员函数提供的就地构造功能。与其构造一个对象,然后使用insert
或push_back
将其添加到向量中,不如调用emplace_back
并简单地将传递给构造器的参数传递给向量持有的类型。然后,该向量将构建并添加一个新的对象实例,而不需要进行复制或移动带来的额外计算,也不需要使用额外的本地内存。
emplace
函数的工作原理是一样的,除了你首先给它传递一个指定位置的迭代器。您可以使用cbegin()
或cend()
向矢量的开头或结尾添加项目。如果你有一个特定的从零开始的索引想要放置一个物品,你可以使用vec.cbegin() + idx
。如果你想在一个项目的末尾放置一些空格,你也可以从cend()
中减去。
vector
提供了更多的功能,所以你肯定应该进一步探索。例如,at
成员函数会在索引处给你一个项目。有一些方法可以告诉向量调整它的内部容量,这样你就有更多的空闲空间——例如,如果你知道你需要正好 125 个项目——或者这样你就最小化了内存使用——如果你添加了它将需要的所有元素并且内存限制很紧。
除了std::vector
,几个类似的容器有不同的用例。std::vector
当您需要极其快速、随机的访问时,它本身就是最佳选择,因为您通常会在集合的最末端添加和删除项目。如果你也需要经常在收藏前添加物品,可以考虑使用std::deque
代替。
先入先出容器使用std::queue
。使用std::stack
作为后进先出容器。
std::map
类提供了一个排序的字典。std::unordered_map
提供哈希表。
std::set
类是一个排序的键控集合,其中存储的项是它自己的键,因此每个元素必须是唯一的。std::unordered_set
是std::set
的未排序的等价物。
std::list
类提供了一个双向链表。std::forward_list
提供单链表。
<algorithm>
表头包含了很多非常有用的功能:比如find
、sort
、copy
之类的东西,以及它们所有的相关方法。学习它们的最好方法是用它们做实验。
C 运行时库中的一些功能可能很有用。一般来说,访问库最好的方式就是包含相关的<c_____>
头文件,比如<cstdlib>
。