插入期间容器std::set的行为

Behaviour of container std::set during Insertion?

本文关键字:set std 插入      更新时间:2023-10-16

插入一个集合时,该集合内部是否多次删除某些对象?我试着像下面的程序一样插入两个MyClass类型的对象,但令我惊讶的是,它调用了类的析构函数,初始插入值2次!我无法理解这背后的逻辑。谁能给点输出的建议?(以粗体突出显示)

#include<stdio.h>
#include<stdlib.h>
#include<set>
 using namespace std;
   struct MyClass 
   {
      double num;
      ~MyClass()
      {
         printf("Destructor called..for val: %lfn", num);
      }
   };
   typedef int (*fun_comp)(MyClass, MyClass);   
  int
   comp(MyClass a, MyClass b)
   {
      return a.num-b.num;
   }
  int
   main()
   {
      fun_comp fptr;
      fptr = &comp;
      set<MyClass, int (*)(MyClass, MyClass)> b(fptr);
      for(int i=3; i< 5; i++)
      {
         printf("started with i: %d....nn", i);
         {
            MyClass m;
            m.num=i*1.134;
            b.insert(m);
            printf("Inserted val: %lfn", m.num);
         }
         printf("ended....nn");
      }
      printf("Done with insert..n");      
      return 0;
   }
输出:

以i开头:3....

插入值:3.402000

为val: 3.402000

结束……

以i: 4开头....

析构函数调用..for val: 4.536000 <-------为什么在插入前释放

析构函数调用..for val: 3.402000 <-------多次调用此值对象的析构函数

析构函数. .呼吁val: 4.536000 & lt ;-------- ??

析构函数. .呼吁val: 3.402000 & lt;——了! !

插入值:4.536000

for val: 4.536000

结束……

插入完成

为val: 3.402000

比较器

int    
comp(MyClass a, MyClass b)
{
   return a.num-b.num;
}  

按值接受其形参。这将创建额外的副本,然后销毁。

通过引用传递会更好。

将比较函数改为使用(const)引用

int comp(const MyClass& a, const MyClass& b)
{
  return a.num-b.num;
}

每次compp被调用时,它都会创建a和b的副本。当compp退出时,这些副本将被销毁。

除了上述几点之外,您的比较函数是无效的,因为它没有指定值的一致顺序。如果a.num=1且b.num=2,则comp(a,b)为真,即a"出现在"b之前,并且comp(b,a)也为真,即b"出现在"a之前。这使得set的行为未定义。

最好为MyClass创建一个小于操作符,并让set<>的默认比较函数完成这项工作:struct MyClass{双num;

  ~MyClass()
  {
     printf("Destructor called..for val: %lfn", num);
  }
  bool operator < (const MyClass &rhs) const
  {
    return num < rhs.num;
  }
};
...
set<MyClass> b;