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

发布于 2024-11-24 21:27:35 字数 1574 浏览 4 评论 0原文

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

#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

析构函数调用..for val: 3.402000

结束...

开始于 i: 4....

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

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

函数 调用了析构函数..for val: 4.536000 <-------- ??

析构函数调用..for val: 3.402000 <------ 再次!!

插入的 val: 4.536000

析构函数调用..for val: 4.536000

结束....

完成插入..

析构函数调用..for val: 3.402000

析构函数调用..for val: 4.536000

While inserting in a set, does the set internally delete some of the objects multiple times? I tried to insert two objects of type MyClass as in following program but to my surprise it calls the destructor of class with initially inserted value 2 times! I am not able to understand any logic behind this. Can anyone give some idea on the output?
(highlighted as bold)

#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 = ∁
      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;
   }

output:
started with i: 3....

Inserted val: 3.402000

Destructor called..for val: 3.402000

ended....

started with i: 4....

Destructor called..for val: 4.536000 <------- why this is deallocated before insertion

Destructor called..for val: 3.402000 <------- multiple call to destructor for this valued object

Destructor called..for val: 4.536000 <-------- ??

Destructor called..for val: 3.402000 <------ again!!

Inserted val: 4.536000

Destructor called..for val: 4.536000

ended....

Done with insert..

Destructor called..for val: 3.402000

Destructor called..for val: 4.536000

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

深海少女心 2024-12-01 21:27:35

比较器

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

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

通过引用传递效果会更好。

The comparator

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

takes its parameters by value. This will create extra copies that are then destroyed.

Passing by reference will work better.

昨迟人 2024-12-01 21:27:35

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

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

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

Change the comparison function to use (const) references

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

Each time your comp is being called it is creating copies of a and b. These copies are being destroyed when comp exits.

我早已燃尽 2024-12-01 21:27:35

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

最好为 MyClass 创建一个小于运算符,并让 set<> 的默认比较函数完成这项工作:
构造我的类
{
双数;

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

In addition to the points made above, your comparison function isn't valid because it doesn't specify a consistent ordering of the values. If a.num=1 and b.num=2 then comp(a,b) is true, meaning that a "comes before" b, and comp(b,a) is also true, meaning that b "comes before" a. This makes the behavior of set undefined.

It's better to create a less-than operator for MyClass and let set<>'s default comparison function do the work:
struct MyClass
{
double num;

  ~MyClass()
  {
     printf("Destructor called..for val: %lf\n", num);
  }
  bool operator < (const MyClass &rhs) const
  {
    return num < rhs.num;
  }
};
...
set<MyClass> b;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文