是否定义了此代码行为?

Wol*_*tan 39 c++ operators

以下代码如何打印到控制台?

map<int,int> m;
m[0] = m.size();
printf("%d", m[0]);
Run Code Online (Sandbox Code Playgroud)

可能答案:

  1. 未定义代码的行为,因为未定义哪个语句m[0]m.size()正由编译器首先执行.因此,它可以打印1以及0.
  2. 它会打印,0因为首先执行赋值运算符的右侧.
  3. 它打印1是因为它operator[]具有完整语句的最高优先级m[0] = m.size().因此,会发生以下事件序列:

    • m[0] 在地图中创建一个新元素
    • m.size() 被调用现在是 1
    • m[0] 获得分配先前返回的(由m.size()) 1
  4. 真正的答案?,我不知道^^

Ste*_*sop 17

我相信未指定 0或1是否存储m[0],但它不是未定义的行为.

LHS和RHS可以按任意顺序出现,但它们都是函数调用,因此它们在开始和结束时都有一个序列点.它们中的两个没有共同的危险,没有中间序列点就可以访问同一个对象.

赋值是实际的int赋值,而不是具有相关序列点的函数调用,因为operator[]返回T&.这简直令人担忧,但它并没有修改在本声明中任何其他位置访问的对象,所以这也是安全的.operator[]当然,它在初始化的位置被访问,但是在返回的序列点之前发生operator[],所以没关系.如果不是,m[0] = 0;也将是未定义的!

但是,操作数的评估顺序operator=不是由标准指定的,因此调用的实际结果size()可能是0或1,这取决于发生的顺序.

但是,以下是未定义的行为.它没有进行函数调用,所以没有任何东西可以阻止size被访问(在RHS上)和修改(在LHS上)没有插入序列点:

int values[1];
int size = 0;

(++size, values[0] = 0) = size;
/*     fake m[0]     */  /* fake m.size() */
Run Code Online (Sandbox Code Playgroud)