首页 > 解决方案 > 将自己的大小插入到 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

这里发生了什么?地图首先使用 set 添加一个新元素,first然后(当地图的大小已经增加时)设置second?我不太明白为什么这会有意义。还是有其他解释?谢谢!

标签: c++c++14stdmap

解决方案


表达式中发生了一些事情

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 开始,情况不再如此。 标准改为:

赋值运算符 (=) 和复合赋值运算符都从右到左分组。都需要一个可修改的左值作为左操作数;它们的结果是一个引用左操作数的左值。如果左操作数是位域,则所有情况下的结果都是位域。在所有情况下,赋值都在左右操作数的值计算之后和赋值表达式的值计算之前进行排序。右操作数在左操作数之前排序。对于不确定顺序的函数调用,复合赋值的操作是单次求值。

它现在保证= m.size()发生在之前m[m.size()],并且你得到你期望的顺序。


推荐阅读