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

时间:2011-07-19 14:19:54

标签: c++ stl insert set

在插入集合时,集合内部是否多次删除了一些对象?我尝试插入两个MyClass类型的对象,如下面的程序,但令我惊讶的是它调用类的析构函数,最初插入值为2次!我无法理解这背后的任何逻辑。任何人都可以对输出有所了解吗? (突出显示为粗体)

#include<stdio.h>
#include<stdlib.h>
#include<set>

 using namespace std;

   struct MyClass 
   {
      double num;

      ~MyClass()
      {
         printf("Destructor called..for val: %lf\n", 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....\n\n", i);
         {
            MyClass m;
            m.num=i*1.134;
            b.insert(m);
            printf("Inserted val: %lf\n", m.num);
         }
         printf("ended....\n\n");
      }

      printf("Done with insert..\n");      
      return 0;
   }

输出: 从i开始:3 ....

插入val:3.402000

destructor called..for val:3.402000

...结束

从i开始:4 ....

析构函数名为..for val:4.536000 &lt; -------为什么在插入之前取消分配

析构函数名为.for val:3.402000 &lt; -------多次调用此值对象的析构函数

析构函数名为.for val:4.536000 &lt; -------- ??

析构函数名为.for val:3.402000 &lt; ------再次!!

插入val:4.536000

destructor called..for val:4.536000

...结束

完成插入..

destructor called..for val:3.402000

destructor called..for val:4.536000

3 个答案:

答案 0 :(得分:11)

将比较函数更改为使用(常量)引用

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

每次调用你的comp时,都会创建a和b的副本。这些副本在退出时会被销毁。

答案 1 :(得分:11)

比较器

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

按值获取其参数。这将创建额外的副本,然后销毁。

通过引用传递将更好。

答案 2 :(得分:4)

除了上面提到的要点之外,您的比较函数无效,因为它没有指定值的一致排序。如果a.num = 1且b.num = 2则comp(a,b)为真,意味着“先于”b,而comp(b,a)也为真,这意味着b“在”之前“ 。这使得set的行为未定义。

最好为MyClass创建一个小于运算符,让set&lt;&gt;的默认比较函数完成工作:    struct MyClass    {       双数;

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