使用operator[]插入元素时,std::map大小不同(vc++与g++)

4
这段代码。
#include <iostream>
#include <map>

int main()
{
    std::map<int, std::size_t> m;
    m[0] = m.size();
    std::cout << m[0] << std::endl;
}

这段代码在vc++g++编译器中分别输出01

  • 这段代码是否有效?
  • 如果有效,哪个编译器是正确的?
  • 直观上我会期望输出1,vc++ 是如何得到 0 的呢?

2
这是未定义行为。对于评估 m[0]m.size() 的顺序没有定义。 - Marek R
@MarekR 谢谢,你能指出在哪里找到解释吗? - AMA
3
@c++17是否改变了这种情况,使得在这种情况下始终首先评估右侧? - G.M.
4
@MarekR 未指定 != 未定义。 - rubenvb
2个回答

7
自 C++17 开始,求值顺序 是有保障的,m.size()m[0] 之前被顺序执行;结果保证是 0

  1. 在每个简单赋值表达式 E1=E2 和每个复合赋值表达式 E1@=E2 中,E2 的每个值计算和副作用都在 E1 的每个值计算和副作用之前被顺序执行

在 C++17 之前,行为是 未指定 的。

顺便说一下,您可以在 Gcc C++17 模式Gcc C++14 模式 下观察到不同的行为。


5
在C++17之前,行为是未指定的,但不是未定义的。m[0]m.size()都是函数调用。它们的执行体不能重叠,即使它们的调用点是未排序的。 - j6t

3

赋值运算符- cppreference.com

当左操作数具有引用类型时,赋值运算符会修改所指对象。

如果左右操作数标识重叠的对象,则行为是未定义的(除非重叠是精确的且类型相同)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接