如何在C++中遍历无序集合?

56

假设我有一个无序集合

unordered_set<int> my_set;
myset.insert(1);
myset.insert(2);
myset.insert(3);

如何遍历它?我不需要按任何顺序遍历-只要能够访问每个元素就可以了。我尝试过

for (int i = 0; i < my_set.size(); i++)
     cout << my_set[i];

无济于事。


1
你可以使用迭代器来进行“迭代”。一个容器应该通过std::begin()std::end()提供给你迭代器。 - Martin York
3个回答

96

你可以使用新的基于范围的for循环:

std::unordered_set<T> mySet;
for (const auto& elem: mySet) {
    /* ... process elem ... */
}

或者,你可以使用更传统的基于迭代器的循环:

std::unordered_set<T> mySet;
for (auto itr = mySet.begin(); itr != mySet.end(); ++itr) {
    /* ... process *itr ... */
}

或者,如果你没有 auto 支持,可能是因为你的编译器不支持 C++11:

std::unordered_set<T> mySet;
for (std::unordered_set<T>::iterator itr = mySet.begin(); itr != mySet.end(); ++itr) {
    /* ... process *itr ... */
}

4
为什么Boost的unordered_set版本会破坏C++11中的auto关键字?我认为你的意思是,“...可能是因为您使用的编译器较旧”,或类似的话。 - Marc
2
@Marc 实际上,这个问题一开始并没有提到 C++11;有人假设必须是 C++11,因为 unordered_set 直到那时才添加,但 Boost 也有一个,所以 OP 可能正在使用旧版的 C++ 与 Boost 的 unordered_set - Michael Mrozek
4
@MichaelMrozek 的说法正确,但有些人可能会在使用 C++11 编译器的同时使用 Boost 版本库。文本中提到“或者,如果您不支持 auto,可能是因为您正在使用无序集合的 Boost 版本”,但是 auto 关键字与使用的类型无关。auto 关键字甚至可以推断那些从 98 标准之前就没有改动过的类的类型。按照原文的描述,似乎 auto 只适用于新的类,或者必须在类中显式地设计。这只是一个小问题,但我认为值得澄清。 - Marc

9

就像任何其他集合一样:

for (auto i = my_set.begin(); i != my_set.end(); ++i) {
    std::cout << (*i) << std::endl;
}

或者使用稍微更通用一些的方式,利用beginend函数的重载(您可以为自己的类型编写重载;它们也适用于普通数组):

for (auto i = begin(my_set); i != end(my_set); ++i) { 
    ...
}

由于某种原因,我的编译器(gcc)不知道“auto”是什么。也许我应该尝试“automobile”、“vehicle”或“car”? :-) 现在认真地说:下面的答案非常有效。 - Travis Banger
1
@TravisBanger 那么你可能是在 C++98 模式下运行,auto 只能从 C++11 开始使用。使用 --std=c++11 或显式命名迭代器类型(参见 @templatetypedef 的答案)。 - Kos

3

到目前为止我没有使用过它们,但我猜想您可以像使用std::set一样使用迭代器:

for(unordered_set<int>::iterator a = my_set.begin(); a != my_set.end(); ++a) {
    int some_int = *a;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接