如何解决将自己的大小插入 std::map
我刚刚在我的代码 (C++14) 中遇到了一个奇怪的错误,这是由 std::map 的意外(至少对我而言)行为引起的。这是一个演示行为的简单示例:
#include <iostream>
#include <map>
int main()
{
std::map<int,int> m;
for(int i = 0; i < 3; ++i) {
m[m.size()] = m.size();
}
for(const std::pair<int,int>& e : m) {
std::cout << e.first << " " << e.second << std::endl;
}
return 0;
}
打印:
0 1
1 2
2 3
我期待:
0 0
1 1
2 2
这里发生了什么?地图首先添加一个设置 first
的新元素,然后(当地图的大小已经增加时)设置 second
?我不太明白为什么这会有意义。或者还有其他解释吗?谢谢!
解决方法
表达式中发生了一些事情
m[m.size()] = m.size();
首先,需要评估 m[m.size()]
和 = m.size()
。在 C++14 中,求值顺序是不确定的。 m[m.size()]
可能首先发生,也可能第二次发生。如果它首先发生,那么您会看到收到的结果。如果它发生在第二个,那么你会得到你期望的输出。
如果你愿意
0 0
1 1
2 2
那么你需要保证自己订购。您可以使用 map::insert()
来做到这一点:
m.insert(m.size(),m.size());
从 C++17 开始,情况不再如此。 The standard 改为:
赋值运算符 (=) 和复合赋值运算符都从右到左分组。所有都需要一个可修改的左值作为它们的左操作数;他们的结果是一个引用左操作数的左值。如果左操作数是位域,则所有情况下的结果都是位域。在所有情况下,赋值顺序都在左右操作数的值计算之后,赋值表达式的值计算之前。右操作数排在左操作数之前。对于不确定顺序的函数调用,复合赋值的操作是一次求值。
它现在保证 = m.size()
发生在 m[m.size()]
之前,并且您得到您期望的顺序。
让我们以更详细的方式写下循环代码:
for(int i = 0; i < 3; ++i) {
int& temp = m.operator[](m.size());
temp = m.size();
}
请注意,调用 operator[]
已经在为它分配值之前插入了默认的初始化元素。因此,在评估分配的右侧时,地图已经增长。
要解决此问题,请确保在使用 operator[]
之前确定大小:
for(int i = 0; i < 3; ++i) {
size_t v = m.size();
m[v] = v;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。