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

std :: set :: erase意外删除了3个元素

如何解决std :: set :: erase意外删除了3个元素

在最后一个erase之前,s1s2中的元素是相同的。

erase的最后一个s1删除集合s1中的1个元素。是的。

erase的最后一个s2删除集合s2中的3个元素。真是出乎意料。

#include <iostream>
#include <cstdlib>
#include <cassert>
#include <set>
#include <functional>

using namespace std;

struct Ev {
  int p = 0;
  int l = 0;
  int r = 0;
  bool open = false;

  friend ostream& operator<<(ostream& os,const Ev& ev);
};

ostream& operator<<(ostream& os,const Ev& ev) {
  os << "p = " << ev.p << ",l = " << ev.l << ",r = " << ev.r << boolalpha
     << ",open = " << ev.open;
  return os;
}

int main() {
  auto lr_cmp = [](const Ev& lhs,const Ev& rhs) {
    return lhs.r == rhs.l;
  };
  set<Ev,decltype(lr_cmp)> s1(lr_cmp);
  set<Ev,decltype(lr_cmp)> s2(lr_cmp);

  assert(s1.insert({0,1,true}).second);
  assert(s1.insert({1,3,true}).second);
  assert(s1.insert({2,4,true}).second);
  assert(s1.insert({0,5,true}).second);
  for (const auto& ev : s1) {
    cout << ev << endl;
  }
  assert(s1.erase({3,false}) == 1);
  
  cout << "--------------------------------" << endl;

  assert(s2.insert({1,true}).second);
  assert(s2.insert({1,true}).second);
  assert(s2.insert({0,true}).second);
  assert(s2.erase({2,false}) == 1);
  assert(s2.insert({2,true}).second);
  for (const auto& ev : s2) {
    cout << ev << endl;
  }
  assert(s2.erase({3,false}) == 1);
  return 0;
}

这是输出

p = 0,l = 0,r = 1,open = true
p = 1,l = 1,r = 3,open = true
p = 2,l = 3,r = 4,open = true
p = 0,l = 4,r = 5,open = true
--------------------------------
p = 0,open = true
prog.exe: prog.cc:51: int main(): Assertion `s2.erase({3,false}) == 1' Failed.
Aborted

解决方法

lr_cmp不是strict weak order。在其他失败中,它不是可传递的。

要求

如果lr_cmp(a,b)==truelr_cmp(b,c)==true,则lr_cmp(a,c)==true

不是这种情况,例如

Ev a {1,1,3,true};
Ev b {1,4,true};
Ev c {0,5,true};

std::cout << std::boolalpha << lr_cmp(a,b) << lr_cmp(b,c) << lr_cmp(a,c);

因此,程序的行为是不确定的。大概是在擦除lr_cmp下的等效元素(或某些?),或者找不到要删除的元素。

equiv(a,b),等于!lr_cmp(a,b) && !lr_cmp(b,a)

的表达式

{3,false}等效于{1,true} {0,true}

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