为什么在分配地图之前将地图元素设置为其大小会增加大小*?

Evg*_*eev 9 c++ map assignment-operator

这是我用来索引令牌的常用模式:检查令牌是否在地图中,如果没有,则将其添加到地图中,分配地图的大小.

在C++中执行此操作时,它会在分配之前意外地增加映射的大小:

#include <cstdio>
#include <map>
using namespace std;

int main() {
    map<char, int> m;
    printf("Size before adding: %d\n", m.size());
    m['A'] = m.size();
    printf("Size after adding: %d\n", m.size());
    printf("What was added: %d\n", m['A']);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

打印出:

Size before adding: 0
Size after adding: 1
What was added: 1
Run Code Online (Sandbox Code Playgroud)

我理解它的方式,它应该评估右侧,即零,然后将其传递给将"A"和零置于地图中的函数.但它似乎是在开始分配之后对其进行评估,这没有任何意义.

在分配操作之前,不应评估右侧吗?

Naw*_*waz 6

从迂腐的角度来说,这种行为是未指明的.

但你的情况会发生什么:

m['A'] = m.size();
Run Code Online (Sandbox Code Playgroud)

mstd::map它创建如果该键不存在,一个新的条目.

在您的情况下,密钥'A'不存在,因此它创建条目,并返回对m.size()您的情况下分配的值(默认创建)的引用.

如上所述,行为是未指定的,因为未指定操作数的评估顺序,这m.size()可能在之前评估m['A'].如果确实如此,那么m['A']将是0,不1.

  • ...以及`or`(`||`),`和`(`&&`)运算符也定义了顺序. (4认同)
  • @EvgeniSergeev:C++没有定义函数参数的评估顺序,所以使用`assign(key,value);`,`key`和`value`仍然以未指定的顺序进行评估.这是为什么你应该通常避免重载`operator,`,`operator ||`和`operator &&`的原因的一部分 - 你失去了为普通运算符保证的顺序. (4认同)
  • 在 C++17 中,这是现在定义的行为,因为保证左侧先于右侧排序。您介意更新答案吗?如果您愿意,我可以吗?谢谢。 (3认同)
  • 是的,所以操作数的评估顺序在C++中一般都没有指定*? (2认同)

Jer*_*fin 5

不。

(第 5.17/1 节):“在所有情况下,赋值顺序都在左右操作数的值计算之后,赋值表达式的值计算之前。”

但是请注意,虽然赋值发生在右操作数和左操作数被求值之后,但在左操作数和右操作数本身的求值之间没有指定顺序。因此,可以先评估左侧,然后评估右侧,反之亦然。