2012-11-05 39 views
9

Tại sao mã sau đây được biên dịch ngay cả khi tôi đã nhận xét A::operator<. Tôi tự hỏi làm thế nào đầu ra của mã sau đây được in theo thứ tự tăng dần mà không có toán tử <. Làm thế nào tôi có thể thay đổi thứ tự giảm dần? (lưu ý: mã này không được biên soạn nếu tôi sử dụng A thay vì A* trừ khi tôi cung cấp một định nghĩa cho A::operator<)Thứ tự các phần tử trong bộ con trỏ

#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. Thứ tự của "chèn" là không liên quan. một tập hợp luôn luôn giữ cho nó giá trị theo thứ tự sử dụng một số '<'. nếu nó không thể sử dụng một '<' nó sẽ không biên dịch. –

+2

Nó chỉ là may mắn. Nó có thể được in theo bất kỳ thứ tự nào. Nó chỉ xảy ra khi 'a1

Trả lời

16

Mã của bạn được biên soạn bởi vì bạn có một tập hợp con trỏ. Vì tập hợp chứa con trỏ và toán tử của bạn không so sánh con trỏ, nhưng thay vào đó, đối tượng thuộc loại A, nó không cần thiết cho bộ này. Có một toán tử so sánh con trỏ hiện có ít hơn so với toán tử được sử dụng trong tập hợp của bạn.

Bạn có thể thay đổi thứ tự bằng cách cung cấp so sánh của riêng bạn thực hiện strict weak ordering:

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

Và nhanh chóng thiết lập của bạn sử dụng nó như tham số mẫu thứ hai.

set<A*, APtrComp> numbers; 
+2

Điều đó gần như đúng. Có một '<' hiện có cho con trỏ, nhưng hành vi của nó là không xác định (và không nhất thiết nhất quán) đối với con trỏ do các phân bổ khác nhau. 'std :: set <>' sử dụng 'std :: less <>' theo mặc định, tuy nhiên, không phải '<'. Và thực hiện một yêu cầu để làm cho 'std :: less' làm việc cho con trỏ. –

+0

@JamesKanze Cảm ơn bạn đã làm rõ.Tôi đã giả định sai rằng 'std :: less' sẽ chỉ gọi toán tử' <'trong trường hợp này. – juanchopanza

+0

@juanchopanza, giải pháp này có một vấn đề, nó KHÔNG duy trì so sánh con trỏ nguyên trùng lặp. Xem bài đăng của tôi: http://stackoverflow.com/questions/20115682/how-to-represent-a-set-of-pointers-with-customized-compare-but-maintaining-the-o –

1

bạn có một bộ con trỏ. thường con trỏ được phân bổ theo thứ tự tăng dần. và con trỏ có toán tử mặc định là <. vì vậy đây là lý do tại sao nó biên dịch và làm việc.

P.s. nó sẽ in cho bạn những giá trị của A1 A2 A3 theo thứ tự này không có vấn đề gì là có giá trị:

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

Nếu bạn còn nhớ số học con trỏ của bạn, tất cả các điểm được đưa ra một tập hợp các toán để sử dụng trong các hoạt động (trong đó bao gồm các nhà điều hành <). Bộ của bạn sẽ sử dụng toán tử mặc định này <.

0

Từ những gì tôi hiểu bạn muốn biết lý do mã biên dịch với A* ngay cả khi bạn không có operator< và cách thay đổi thứ tự từ tăng dần đến giảm dần.

Nó biên dịch vì nó đang sử dụng operator< với địa chỉ con trỏ.
thay đổi cout << (*itr)->x << endl;
để cout << (*itr)->x << ' ' << *itr << endl; và bạn sẽ thấy nó dễ dàng :)

Nó là bình thường rằng mã không biên dịch mà không có sự operator< nếu bạn đang sử dụng set<A>. Nó sẽ không biết những gì để so sánh để chèn các thành viên được sắp xếp. Vì vậy, bạn phải cung cấp cho nhà điều hành đó!

Nếu bạn muốn tiếp tục sử dụng con trỏ, bạn có thể sử dụng mã do @juanchopanza cung cấp.

Các vấn đề liên quan