三元运算符的意外行为

Unexpected behavior from ternary operator

本文关键字:意外 运算符 三元      更新时间:2023-10-16

当我运行这段代码时:

#include <iostream>
#include <map>
using namespace std;
void f1() {
    map<int, int> m;
    m[5] = m.find(5) == m.end() ? 1 : 2;
    cout << m[5] << endl;
}
void f2() {
    map<int, int> m;
    if (m.find(5) == m.end())
        m[5] = 1;
    else
        m[5] = 2;
    cout << m[5] << endl;
}
int main() {
    f1();
    f2();
    return 0;
}

得到以下输出:

2
1

为什么我得到错误的输出,当我使用三元操作符?

函数调用的顺序是不确定的,会影响您的结果。考虑:

void f1()
{
    map<int, int> m;
    int& result = m[5]; // creates m[5]
    auto it = m.find(5); // finds the empty m[5] created above
    int value = (it == m.end())? 1: 2;
    result = value;
    std::cout << m[5] << std::endl;
}

这是你写的代码的一个完全合法的实现。

三元操作符没有问题。这样就可以了:

bool notfound = (m.find(5) == m.end());
m[5] = notfound? 1: 2;

重要的是m[5]能否先于m.find(5)求值

在此语句中

m[5] = m.find(5) == m.end() ? 1 : 2;

通过将对象m[5]放在赋值的左侧来创建对象m[5]。因此m.find(5) != m.end(),因为m[5]已经存在。

实际上存在未定义的行为,因为赋值的左操作数和右操作数的求值顺序没有指定。