插入期间容器 std::set 的行为?
在插入集合时,集合内部是否多次删除某些对象?我尝试插入两个 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 = ∁
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
比较器
按值获取其参数。这将创建额外的副本,然后将其销毁。
通过引用传递效果会更好。
The comparator
takes its parameters by value. This will create extra copies that are then destroyed.
Passing by reference will work better.
将比较函数更改为使用 (const) 引用
每次调用您的 comp 时,它都会创建 a 和 b 的副本。当 comp 退出时,这些副本将被销毁。
Change the comparison function to use (const) references
Each time your comp is being called it is creating copies of a and b. These copies are being destroyed when comp exits.
除了上面指出的几点之外,您的比较函数无效,因为它没有指定一致的值顺序。如果 a.num=1 且 b.num=2 则 comp(a,b) 为真,表示 a“出现在”b 之前,并且 comp(b,a) 也为真,表示 b“出现在 a 之前” 。这使得 set 的行为未定义。
最好为 MyClass 创建一个小于运算符,并让 set<> 的默认比较函数完成这项工作:
构造我的类
{
双数;
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;