2009-10-16 82 views
0

我寫了這個程序,用一個仿函數這種種的一些整數:C++函數 - 意外的行爲?

#include<iostream> 
#include<list> 
#include<set> 

using namespace std; 

struct IntSorter 
{ 
    unsigned int comparisons; 
    IntSorter() 
    { 
     std::cout << "new intsorter" << std::endl; 
     comparisons = 0; 
    } 

    bool operator() (const int &a, const int &b) 
    { 
     std::cout << "c is " << comparisons << std::endl; 
     ++comparisons; 
     std::cout << "c is now " << comparisons << std::endl; 
     return a<b; 
    } 
}; 

int main(int argc, char *argv[]) 
{  
    list<int> my_list; 
    my_list.push_back(4); 
    my_list.push_back(3); 
    my_list.push_back(5); 
    my_list.push_back(1); 

    IntSorter s; 
    my_list.sort(s); 

    for (list<int>::iterator it=my_list.begin(); it!=my_list.end(); it++) 
    { 
     std::cout << *it << std::endl; 
    } 

    return 0; 

} 

的分揀工作正常,但計數的比較次數的部分給出結果沒想到:

./prog -a -b -c -d 
new intsorter 
c is 0 
c is now 1 
c is 0 
c is now 1 
c is 0 
c is now 1 
c is 1 
c is now 2 
c is 2 
c is now 3 
1 
3 
4 
5 

我在想結構會被重用,計數和存儲比較次數。但是,它似乎會複製它,或者打印出來的數字是1,1,1,2,3而不是1,2,3,4,5。我究竟做錯了什麼?

回答

2

你真的沒有做錯任何事情。問題完全在於你的期望 - 分揀機是通過價值傳遞的,所以當你通過它時,只有最少一份。排序函數可以自由地創建更多副本(例如,遞歸排序可能會將副本傳遞給每個遞歸調用)。

這裏有一個簡單的教訓:任何這樣的對象應該是便宜來創建和/或複製。

+1

而要證明這一點,你也可以的「這個」在運營商()以及輸出值。 – 2009-10-16 20:15:08

+0

這是一個很好的觀點。 – 2009-10-16 20:33:52

3

你在正確的軌道上。 std :: list :: sort通過值獲取函數對象。因爲它的工作,它傳遞函數對象的副本,這意味着比較成員數據也被複制。

你沒有做錯任何事情,只是你不能使用這樣的函子。

使std :: list :: sort做最簡單的方法就是在函數中嵌入對外部計數器對象的引用。在每個比較中,轉發對該對象的調用。在std :: list :: sort返回之後,你將有總數。

0

至於提到它是按值傳遞: 一個簡單的解決方案是:

struct IntSorter 
{ 
    unsigned int& comparisons; 
    IntSorter(unsigned int& c) 
     :comparisons(c) 
    {} 
    // Other Stuff 
}; 

// In main: 
unsigned int count = 0; 
my_list.sort(IntSorter(count));