将自己的大小插入 std::map [英] Inserting its own size to std::map

查看:47
本文介绍了将自己的大小插入 std::map的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚在我的代码 (C++14) 中遇到了一个奇怪的错误,这是由 std::map 的意外(至少对我而言)行为引起的.这是一个演示行为的简单示例:

I just encountered a weird bug in my code (C++14) caused by the unexpected (for me at least) behavior of std::map. Here's a simple example demonstrating the behavior:

#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?我不太明白为什么这会有意义.或者还有其他解释吗?谢谢!

What is going on here? The map first adds a new element with first set and only then (when the map's size has already increased) sets second? I don't quite understand why this would make sense. Or is there some other explanation? Thanks!

推荐答案

表达式中发生了一些事情

There is a few thing that happens in the expression

m[m.size()] = m.size();

首先,需要计算 m[m.size()]= m.size() .在 C++14 中,求值顺序是不确定的.m[m.size()] 可能首先发生,也可能第二次发生.如果它首先发生,那么您会看到收到的结果.如果它发生在第二个,那么你会得到你期望的输出.

First, m[m.size()] and = m.size() need to be evaluated. In C++14, that evaluation order is indeterminately sequenced. m[m.size()] might happen first, or it might happen second. If it happens first, then you see the results you received. If it happens second, then you get the output that you expected.

如果你愿意

0 0
1 1
2 2

那么你需要保证自己订购.您可以使用 map::insert() 来做到这一点:

Then you need to guarantee that ordering yourself. You can use map::insert() to do just that:

m.insert(m.size(), m.size());


从 C++17 开始,情况不再如此.标准改为:

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

The assignment operator (=) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand; their result is an lvalue referring to the left operand. The result in all cases is a bit-field if the left operand is a bit-field. In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression. The right operand is sequenced before the left operand. With respect to an indeterminately-sequenced function call, the operation of a compound assignment is a single evaluation.

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

It now guarantees that = m.size() happens before m[m.size()], and you get the order that you expect.

这篇关于将自己的大小插入 std::map的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆