在c++ unordered_map中高效地使用[]操作符
Using The [] Operator Efficiently With C++ unordered_map
首先,有人可以澄清是否在c++中使用[]操作符与unordered_map一起用于查找包装了对find()方法的调用,或者使用[]操作符比find()更快?
其次,在下面的代码段中,我怀疑在键不在unordered_map中的情况下,我通过map[key] = value
行执行第二次查找,以便在键不存在时使用[]操作符替换在那里创建的默认值。
是真的吗?如果是这样,是否有一种方法(也许是通过使用指针或其他东西),我可能只执行一次查找在任何情况下(也许是通过存储地址的地方放置一个值/读取一个值),仍然实现相同的功能?显然,如果这样的话,这将是一个有用的效率提高。
下面是修改后的代码摘录:
int stored_val = map[key]; // first look up. Does this wrap ->find()??
// return the corresponding value if we find the key in the map - ie != 0
if (stored_val) return stored_val;
// if not in map
map[key] = value;
/* second (unnecessary?) look up here to find position for newly
added key entry */
return value;
operator[]
将为您插入一个带有默认构造值的条目(如果没有的话)。它相当于
iterator iter = map.find(key);
if(iter == map.end())
{
iter = map.insert(value_type(key, int())).first;
}
return *iter;
operator[]
可以比手动使用find()
和insert()
更快,因为它可以节省重新散列密钥的时间。
在代码中处理多次查找的一种方法是获取对值的引用:
int &stored_val = map[key];
// return the corresponding value if we find the key in the map - ie != 0
if (stored_val) return stored_val;
// if not in map
stored_val = value;
return value;
注意,如果该值在映射中不存在,operator[]
将默认构造并插入一个。因此,虽然这将避免多次查找,但如果与默认构造+赋值比复制或移动构造慢的类型一起使用,它实际上可能会更慢。
对于int
,它便宜地默认构造为0,您可以将0视为表示空的幻数。这看起来就像您的示例中的情况。
如果你没有这样的神奇数字,你有两个选择。你应该使用什么取决于你计算这个值的成本有多高。
首先,当散列键很便宜但计算值很昂贵时,find()
可能是最好的选择。这将哈希两次,但只在需要时计算值:
iterator iter = map.find(key);
// return the corresponding value if we find the key in the map
if(iter != map.end()) return *iter;
// if not in map
map.insert(value_type(key, value));
return value;
但是如果你已经得到了值,你可以非常有效地做到这一点——也许比上面使用引用+幻数更有效:
pair<iterator,bool> iter = map.insert(value_type(key, value));
return *iter.first;
如果map.insert(value_type)
返回的bool值为true,则表示插入了该项。否则,它已经存在,没有做任何修改。迭代器返回指向映射中插入值或现有值的点。对于您的简单示例,这可能是最好的选择。
可以检查元素是否存在,和如果不存在则插入一个新元素,使用特殊的insert
函数返回一个pair<iterator, bool>
,其中布尔值告诉您该值是否已实际插入。例如,下面的代码:
unordered_map<char, int> mymap;
pair<unordered_map<char,int>::iterator,bool> ret;
// first insert function version (single parameter):;
mymap.insert ( pair<char,int>('z',200) );
ret=mymap.insert (pair<char,int>('z',500) );
if (ret.second==false)
{
cout << "element 'z' already existed";
cout << " with a value of " << ret.first->second << endl;
}
如果配对<'z',200>
不存在,这里的代码将其插入到映射中。如果返回的元素对的第二个元素的值为真,则返回插入元素的迭代器;如果返回的元素对的第二个元素为假,则返回元素实际所在的迭代器。
首先,有人可以澄清是否在c++中使用[]操作符与unordered_map一起用于查找包装了对Find()方法的调用,或者使用[]操作符比Find()更快?
没有这样的规则。[]
的实现可以使用find()
,它可以自己执行查找,也可以将查找委托给find()
内部使用的某个私有方法。
也不能保证哪一个更快。find()
涉及构造和返回迭代器的开销,而[]
在键不存在的情况下可能会慢一些,因为在这种情况下它会插入一个新值。
(…)是否有一种方法(可能是通过使用指针或其他东西),我可能只执行一次查找在任何情况下(…)
如果键不在映射中,[]
将插入一个新的默认构造值,并返回一个引用。因此,您可以存储该引用以保存第二次查找:
int& stored_val = map[key]; // Note the reference
if (stored_val) return stored_val;
// Use the reference to save a second lookup.
stored_val = value;
return value;
- C++中高效的大型稀疏块压缩线性方程
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 如何在C++中高效地构造随机骰子
- 如何实现高效的算法来计算大型数据集的多个不同值?
- 更高效地在微控制器上对C++进行基准测试
- 从C++无序集合中高效提取元素
- 高效的字符串截断算法,按顺序删除相等的前缀和后缀
- C++中特征对角矩阵类型的高效存储
- 高效简单的结构比较运算符
- 使用 Rcpp 的高效矩阵子集
- C++ 包含特征矩阵的类的高效算术运算符重载
- CUDA 高效的 nd-array(张量)切片
- 大多数基本类型的高效二进制序列化
- RAM高效C++属性
- 如何为球形物体和三角形地形提供高效的碰撞检测和响应
- 如何实现四个 i8 元素组的高效_mm256_madd_epi8点积
- 为什么map有操作符[],set没有
- 如何在嵌套映射(C++)中高效地查找密钥
- 在C++中高效地保存许多连续记录的图像
- 在c++ unordered_map中高效地使用[]操作符