2011-03-24 282 views
2

全部-C++ std :: set插入导致段错误

我不能完全弄清楚为什么这段代码导致分段错误......任何帮助将是伟大的。

#include <iostream> 
#include <set> 

using namespace std; 

class A{ 
public: 
    int _x; 

    A(int x){ 
     _x = x; 
    } 
}; 

bool fncomp(A a1, A a2){ 
    return a1._x < a2._x; 
} 

int main(){ 
    bool(*fn_pt)(A,A) = fncomp; 

    set<A, bool(*)(A,A)> testSet; 
    for(int i=0; i<10; i++){ 
     cout << i << endl; 
     A a(i); 
     testSet.insert(a); 
    } 
} 

输出是:

0 
1 
Segmentation Fault 

回答

8

好吧,看在你的代码。你宣布函数fncomp,但你真的在任何地方使用该函数吗?你用它初始化了fn_pt,但是没有在任何地方使用fn_pt。你觉得这不奇怪吗?如果您从不要求您的设置对象使用该功能,您如何期望testSet对象知道您希望它使用fncomp作为比较器?

您用普通函数指针类型bool(*)(A,A)作为比较器类型声明了您的集合testSet。这就是比较器的型号。现在,你必须通过构造函数的参数来比较实际传递给你设定的目标

set<A, bool(*)(A,A)> testSet(fn_pt); 

set<A, bool(*)(A,A)> testSet(fncomp); 

(你并不真正需要的是中间的指针fn_pt)。

你忘了这么做,并且set对象使用了比较器的默认构造器参数值,在这种情况下它是一个空指针。因此,每当您的testSet对象尝试比较两个元素时,它都会通过空指针执行函数调用。难怪它崩溃。

+0

啊......这似乎已经完成了帽子戏法。愚蠢的错误!再次感谢! – Andrew 2011-03-24 20:25:55

+0

我刚碰到这个。这是一个愚蠢的错误。但我不明白为什么默认的构造函数是允许的。我声明该集合需要一个函数,并且我不用一个构造它,这没关系? – philo 2013-03-14 01:01:15

+0

@philo:嗯,大多数人使用*功能对象*作为比较器,即重载'operator()'的类。在这种情况下,类类型被用作模板参数,而比较对象本身(构造函数参数)通常被默认构造。一个默认构造的比较对象正是大多数情况下需要的,所以它工作正常。 – AnT 2013-03-14 01:40:05

1

你没有得到关于未使用变量fn_pt的编译器警告吗?

变量testSet具有指定类型bool(*)(A,A)的内部比较器。由于您没有初始化它,因此它被默认初始化为NULL。所以当testSet试图插入A(1)时,它试图调用一个空函数指针来确定哪个顺序是正确的。

你大概的意思是:

set<A, bool(*)(A,A)> testSet(fn_pt);