微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在三元运算符corect的其他部分增加映射迭代器吗?

如何解决在三元运算符corect的其他部分增加映射迭代器吗?

方法1中的代码是否不正确(使用三元运算符)。 ++++在这里是否有未定义的评估顺序。或两种方法相同:

方法1:

struct X
{
    int id;
    int j;
};

void delete_data_from_map(map<int,X>& my_map,int const id)
{
    for(auto it {my_map.begin()}; it != my_map.end();)
    {
        it = (it->second.id == id) ? my_map.erase(it) : ++it;
    }
}

方法2:

void delete_data_from_map(map<int,int const id)
{
    for(auto it {my_map.begin()}; it != my_map.end();)
    {
        if(it->second.id == id)
             it = my_map.erase(it);
        else ++it;
    }
}

解决方法

有三个问题在起作用。一种是三元运算符的语义:仅评估条件运算符的一种可能性。来自[expr.cond]:

仅计算第二个和第三个表达式之一。

此外,您可以依靠所选择的条件直到条件完全结束才开始:

与第一个表达式相关的每个值计算和副作用要在与第二个或第三个表达式相关的每个值计算和副作用之前进行排序。

第二个问题是it = ++it;的语义:在递增之后分配类型时,类型在逻辑上的行为可能不同。通常,我们不期望类型会改变可观察的行为,但是我们无法分辨。最好写下您想要的内容:仅增加++it;

最后,主题为it = ++it;是UB C-17之前的版本,以及是否要将代码绑定到该版本。


结论:为此最好写一个简单的if,正是因为精确的语义和对UB的恐惧是不值得的。

,

您没有提供足够的上下文,因此,我想您要搜索其他属性(不是键)上的多个项目并将其删除。

如果该假设正确,那么这两种方法都很好,因为如果当前元素与您的搜索条件不匹配,则您将迭代器增加到下一个元素。

尽管,我仍然推荐if-else,因为它对读者来说更清楚,而且避免了三元版本可能存在的任何缠结的序列点问题。

,

由于it的类型为map<int,X>::iterator,因此表达式

it = (it->second.id == id) ? my_map.erase(it) : ++it;
在这种情况下,

是定义明确的 ,因为++it实际上是一个函数调用;函数内部发生的更新在赋值表达式之前排序。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。