2012-11-05 19 views
9

Dlaczego poniższy kod jest kompilowany, mimo że skomentowałem A::operator<. Zastanawiam się, jak wyjście z następującego kodu jest drukowane w porządku rosnącym, bez operatora <. Jak mogę zmienić kolejność na malejącą? (uwaga: ten kod nie zostanie skompilowany, jeśli mogę użyć A zamiast A* chyba przedstawić definicję dla A::operator<)Kolejność elementów w zestawie wskaźników

#include <iostream> 
#include <set> 

using namespace std; 

class A 
{ 
public: 
    A(int v):x(v){} 
    virtual ~A(){} 
    int x; 
    /*bool operator<(const A &a) const 
    { 
     return x > a.x; 
    }*/ 
}; 

int main() 
{ 
    set<A*> numbers; 
    A* a1 = new A(1); 
    A* a2 = new A(2); 
    A* a3 = new A(3); 
    numbers.insert(a2); 
    numbers.insert(a3); 
    numbers.insert(a1); 
    for(set<A*>::iterator itr = numbers.begin();itr!=numbers.end();itr++) 
    { 
     cout << (*itr)->x << endl; 
    } 
    // output: 1 2 3 
    return 0; 
} 
+0

P.s. Kolejność "wstawiania" jest nieistotna. zestaw ZAWSZE zachowuje wartości w porządku używając jakiegoś '<'. gdyby nie mógł użyć '<', nie skompiluje się. –

+2

To tylko głupie szczęście. Może być wydrukowany w dowolnej kolejności. Tak się składa, że ​​'a1

Odpowiedz

16

Twój kod zostanie skompilowany, ponieważ masz zestaw wskaźników. Ponieważ zestaw zawiera wskaźniki, a twój operator nie porównuje wskaźników, a raczej obiektów typu A, nie jest potrzebny dla zestawu. Istnieje istniejący wskaźnik mniejszy niż operator porównania, który jest używany w twoim zestawie.

Można zmienić kolejność dostarczając własny komparator wykonawczych strict weak ordering:

struct APtrComp 
{ 
    bool operator()(const A* lhs, const A* rhs) const { /* implement logic here */ } 
}; 

I instancji zestawu używając go jako drugi parametr szablonu.

set<A*, APtrComp> numbers; 
+2

To prawie w porządku. Istniejące '<' dla wskaźników, ale jego zachowanie jest nieokreślone (i niekoniecznie spójne) dla wskaźników wynikających z różnych przydziałów. 'std :: set <>' domyślnie używa 'std :: less <>', a nie '<'. Implementacja jest wymagana, aby utworzyć 'std :: less' dla wskaźników. –

+0

@JamesKanze Dzięki za wyjaśnienie.Błędnie założyłem, że 'std :: less' po prostu wywoła operację' <'w tym przypadku. – juanchopanza

+0

@juanchopanza, to rozwiązanie ma problem, NIE zachowuje duplikatu porównania surowego wskaźnika. Zobacz mój wpis: http://stackoverflow.com/questions/20115682/how-to-represent-a-set-of-pointers-with-customized-compare-but-maininging-to –

1

masz zestaw wskaźników. zwykle wskaźniki są przydzielane w porządku rosnącym. i wskaźniki mają domyślny operator <. dlatego to kompilacja i praca.

P.s. wypisze Ci wartość A1 A2 A3 w tej kolejności, bez względu na to, co tam wartości:

... 
A* a1 = new A(9); 
A* a2 = new A(5); 
A* a3 = new A(1); 
... 
// output: 9 5 1 
1

Jeśli pamiętasz wskaźnik arytmetyki, wszystkie punkty otrzymują zestaw operatorów do wykorzystania w operacjach (która obejmuje operatora <). Twój zestaw użyje tego domyślnego operatora <.

0

Z tego co rozumiem, chcesz wiedzieć, dlaczego kod kompiluje się z A*, nawet jeśli nie masz operator< i jak zmienić kolejność od rosnącej do malejącej.

Kompiluje się, ponieważ używa adresu operator< z adresem wskaźnika.
zmiana cout << (*itr)->x << endl;
do cout << (*itr)->x << ' ' << *itr << endl; i zobaczysz go łatwo :)

To normalne, że kod nie kompiluje bez operator< jeśli używasz set<A>. Nie będzie wiedział, co porównać, aby wstawić posortowane elementy. Musisz więc zapewnić tego operatora!

Jeśli chcesz dalej używać wskaźników, możesz użyć kodu podanego przez @juanchopanza.

Powiązane problemy