为什么 std::map 不提供key_iterator和value_iterator
Why doesn’t std::map provide key_iterator and value_iterator?
我在 C++03 环境中工作,将函数应用于映射的每个键是很多代码:
const std::map<X,Y>::const_iterator end = m_map.end();
for (std::map<X,Y>::const_iterator element = m_map.begin(); element != end; ++element)
{
func( element->first );
}
如果存在key_iterator
,则相同的代码可以利用std::for_each
:
std::for_each( m_map.key_begin(), m_map.key_end(), &func );
那么为什么不提供呢?有没有办法使第一种模式适应第二种模式?
是的,这是一个愚蠢的缺点。 但它很容易纠正:您可以编写自己的泛型key_iterator类,该类可以从map(对)迭代器构造。 我已经做到了,它只是几行代码,然后制作value_iterator也是微不足道的。
std::map<K, V>
不需要为键和/或值提供迭代器:这样的迭代器可以很容易地基于现有的迭代器构建。好吧,这并不像应该/可能的那样容易,但它肯定是可行的。我知道 Boost 有一个迭代器适配器库。
真正的问题可能是:为什么标准C++库不提供迭代器适配器来项目迭代器?在我看来,简短的回答是:因为,一般来说,你不想修改迭代器来选择访问的属性!您宁愿希望投影或更一般地转换访问的值,但仍保持相同的位置概念。表述不同,我认为有必要将定位的概念(即推进迭代器并测试其位置是否有效)与访问给定位置的属性分开。我设想的方法看起来像这样:
std::for_each(m_map.key_pm(), m_map.begin(), m_map.end(), &func);
或者,如果您知道从映射的迭代器获得的底层结构是一个std::pair<K const, V>
(就像std::map<K, V>
的情况一样,但不一定是类似于关联容器的其他容器的情况;例如,基于 B 树的关联容器将受益于将键和值拆分为单独的实体):
std::for_each(_1st, m_map.begin(), m_map.end(), &func);
我的 STL 2.0 页面是一篇 [不完整] 的文章,其中包含更多关于我认为应该如何改进标准C++库算法的细节,包括上述将迭代器分为定位(游标)和属性访问(属性映射)。
那么为什么不提供呢?
我不知道。
有没有办法使第一种模式适应第二种模式?
除了制作"键迭代器"(参见我的评论和其他答案)之外,您还可以围绕func
编写一个小包装器,例如:
class FuncOnFirst { // (maybe find a better name)
public:
void operator()(std::map<X,Y>::value_type const& e) const { func(e.first); }
};
然后使用:
std::for_each( m_map.begin(), m_map.end(), FuncOnFirst() );
稍微通用一点的包装器:
class FuncOnFirst { // (maybe find a better name)
public:
template<typename T, typename U>
void operator()(std::pair<T, U> const& p) const { func(p.first); }
};
key_iterator
或value_iterator
,因为std::map
的value_type
是一个std::pair<const X, Y>
,这就是for_each()
调用的函数(或函子)将要操作的内容。 单个迭代器不会提高性能,因为pair
聚合在映射使用的二叉树的基础节点中。
通过std::pair
访问键和值几乎不费力。
#include <iostream>
#include <map>
typedef std::map<unsigned, unsigned> Map;
void F(const Map::value_type &v)
{
std::cout << "Key: " << v.first << " Value: " << v.second << std::endl;
}
int main(int argc, const char * argv[])
{
Map map;
map.insert(std::make_pair(10, 20));
map.insert(std::make_pair(43, 10));
map.insert(std::make_pair(5, 55));
std::for_each(map.begin(), map.end(), F);
return 0;
}
这给出了输出:
Key: 5 Value: 55
Key: 10 Value: 20
Key: 43 Value: 10
Program ended with exit code: 0
- 瓦尔格林德:数学函数"Conditional jump or move depends on uninitialised value(s)"
- 为什么static_assert错误:即使我传递常量"expression must have a constant value"?
- 为什么我会" void value not ignored as it ought to be"?
- 方法错误"not all control paths return a value"和方法不返回值
- 在调试模式下引发C++ "deque iterator not dereferencable"异常
- std::iterator::reference 必须是引用吗?
- C++/SDL "initial value of reference to a non-const must be an lvalue"
- 如何在 c++ 中理解这样的代码 [request->headers().Method()->value().getStringView())]
- std::<key-value>不同类型的对向量
- c++ visual studio 64bit | save registers value
- 初始化数组、"memset"或" {//value} "的最佳方法是什么?
- 如何解决类成员函数中的"return a value"错误?
- bsoncxx: document::view vs document::value
- .value( "key" , default) 不适用于空的 json 对象吗?
- 为什么unordered_set<string::iterator>不起作用?
- 如何在C++中设置演员的"Render Custom Depth Pass"和"Depth Stencil Value"?
- Qt 错误:QSqlQuery::value:尝试从表中检索统计信息时未定位在有效记录上 (QComboBox)
- 造成致命错误:boost/fusion/iterator/equal_to.hpp 没有这样的文件或目录
- Visual accept std::string from std::byte iterator
- 马洛克会在 C++17 年返回"invalid pointer value"吗?