2011-03-24 287 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);